From bd0555e3dd86a58e6ad59f043b683641add3ce10 Mon Sep 17 00:00:00 2001 From: TheIcarusWings <10465470+TheIcarusWings@users.noreply.github.com> Date: Fri, 12 Jun 2026 14:21:59 +0100 Subject: [PATCH] fix(desktop): preserve framework symlinks in staged mac launcher bundle buildMacLauncher copies Electron.app with cpSync, which rewrites the framework's relative symlinks (Resources -> Versions/Current/Resources) into absolute paths pointing back into node_modules. Sandboxed helper processes cannot follow symlinks that escape the app bundle, so `pnpm start:desktop` crashed on macOS with repeated "icudtl.dat not found in bundle" and a fatal unusable GPU process. Pass verbatimSymlinks to keep the bundle self-contained. Also bump LAUNCHER_VERSION so previously staged bundles with rewritten symlinks are invalidated and re-copied instead of being reused by the metadata check. --- apps/desktop/scripts/electron-launcher.mjs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/apps/desktop/scripts/electron-launcher.mjs b/apps/desktop/scripts/electron-launcher.mjs index 8f20001bbb0..a25d08996bd 100644 --- a/apps/desktop/scripts/electron-launcher.mjs +++ b/apps/desktop/scripts/electron-launcher.mjs @@ -30,7 +30,7 @@ export const APP_BUNDLE_ID = isDevelopment ? `com.t3tools.t3code.dev.${devBundleIdSuffix || "local"}` : "com.t3tools.t3code"; const APP_PROTOCOL_SCHEMES = isDevelopment ? ["t3code-dev"] : ["t3code"]; -const LAUNCHER_VERSION = 10; +const LAUNCHER_VERSION = 11; const defaultIconPath = join(desktopDir, "resources", "icon.icns"); const developmentMacIconPngPath = join(repoRoot, "assets", "dev", "blueprint-macos-1024.png"); @@ -295,7 +295,11 @@ function buildMacLauncher(electronBinaryPath) { } rmSync(targetAppBundlePath, { recursive: true, force: true }); - cpSync(sourceAppBundlePath, targetAppBundlePath, { recursive: true }); + // verbatimSymlinks keeps the framework's relative symlinks intact + // (e.g. Resources -> Versions/Current/Resources). Without it cpSync + // rewrites them to absolute paths into node_modules, which escape the + // bundle and crash sandboxed helper processes (icudtl.dat not found). + cpSync(sourceAppBundlePath, targetAppBundlePath, { recursive: true, verbatimSymlinks: true }); patchMainBundleInfoPlist(targetAppBundlePath, iconPath); patchHelperBundleInfoPlists(targetAppBundlePath); if (isDevelopment) {