{"record":{"id":"f029ef0dd3f635b2","repo":"musistudio/claude-code-router","slug":"failed-to-open-zcode-app-spawnerror","errorCode":null,"errorMessage":"Failed to open ZCode App: ${spawnError}","messagePattern":"Failed to open ZCode App: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/cli/src/cli.ts","lineNumber":202,"sourceCode":"      applyClaudeAppGatewayConfig(launchConfig);\n      applyClaudeAppGatewayConfig(launchConfig, {\n        backup: false,\n        dataDir: resolveClaudeAppProfileUserDataDir(configDir, profile),\n        refreshModelDiscoveryCache: true\n      });\n      const launch = await launchClaudeAppProfile(configDir, profile, launchConfig);\n      const spawnError = await waitForImmediateSpawnError(launch.child, 500);\n      if (spawnError) {\n        throw new Error(`Failed to open Claude App: ${spawnError}`);\n      }\n      process.stdout.write(`Opened Claude App with ${profile.name || profile.id}.\\n`);\n      return;\n    }\n    if (profile.agent === \"zcode\" && resolvedSurface === \"app\" && profileOptions.agentArgs.length === 0) {\n      const launch = launchZcodeAppProfile(configDir, profile, launchConfig);\n      const spawnError = await waitForImmediateSpawnError(launch.child, 500);\n      if (spawnError) {\n        throw new Error(`Failed to open ZCode App: ${spawnError}`);\n      }\n      process.stdout.write(`Opened ZCode App with ${profile.name || profile.id}.\\n`);\n      return;\n    }\n\n    const plan = buildProfileLaunchPlan(configDir, profile, resolvedSurface, profileOptions.agentArgs);\n\n    if (path.isAbsolute(plan.command) && !existsSync(plan.command)) {\n      throw new Error(`Profile launcher was not found: ${plan.command}. Open CCR once or re-save the profile.`);\n    }\n\n    const childEnv = {\n      ...process.env,\n      ...plan.env,\n      ...botGatewayProfileEnv(launchConfig, profile, resolvedSurface)\n    };\n    delete childEnv.ELECTRON_RUN_AS_NODE;\n","sourceCodeStart":184,"sourceCodeEnd":220,"githubUrl":"https://github.com/musistudio/claude-code-router/blob/99f24806c6a2c660b16e53e95211c517448a6c90/packages/cli/src/cli.ts#L184-L220","documentation":"Re-thrown from installUpdate when the actual install action (e.g. autoUpdater.quitAndInstall or staging work) throws. The caught error is formatted into status.lastError and thrown back to the caller.","triggerScenarios":"canInstall is true, installUpdate proceeds, but the install invocation throws — commonly when quitAndInstall is blocked, the staged file is corrupt/locked (antivirus), or the updater misconfigures itself at install time.","commonSituations":"Antivirus/EDR locking the staged installer on Windows; staged update checksum mismatch; quitAndInstall called during app shutdown races; permissions issues writing to the install directory.","solutions":["Inspect the formatted message for the underlying electron-updater error","Re-download the update (checksum/lock issues often resolve) then retry install","On Windows, whitelist the app cache dir in antivirus or retry after locks release","Ensure installUpdate isn't invoked during quit/shutdown lifecycle races"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  await updateService.installUpdate();\n} catch (error) {\n  logger.error('install failed', formatError(error));\n  // suggest re-download; AV locks and corrupt staging often resolve on retry\n}","preventionTips":["Don't call installUpdate during quit/shutdown lifecycle races","Whitelist the update cache directory in antivirus policies","On install failure, re-run downloadUpdate to restage before retrying"],"tags":["electron","auto-update","install","filesystem"],"backgroundTag":"update-install-failed","analyzedSha":"99f24806c6a2c660b16e53e95211c517448a6c90","analyzedAt":"2026-08-27T04:11:01.184Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}