musistudio/claude-code-router · error · Error
Failed to open ZCode App
Error message
Failed to open ZCode App: ${spawnError} What it means
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.
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
Defensive patterns
Strategy: try-catch
Try / catch
try {
await updateService.installUpdate();
} catch (error) {
logger.error('install failed', formatError(error));
// suggest re-download; AV locks and corrupt staging often resolve on retry
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Failed to open Claude App
- Claude App profiles do not support agent arguments.
- [deep-link] Failed to register
- Only http and https URLs can be opened.
- Origin redirected to
AI-assisted analysis of musistudio/claude-code-router@99f24806c6 (2026-08-27).
Data as JSON: /api/errors/f029ef0dd3f635b2.
Report an issue: GitHub.
Appendix: source
Thrown at packages/cli/src/cli.ts:202
applyClaudeAppGatewayConfig(launchConfig);
applyClaudeAppGatewayConfig(launchConfig, {
backup: false,
dataDir: resolveClaudeAppProfileUserDataDir(configDir, profile),
refreshModelDiscoveryCache: true
});
const launch = await launchClaudeAppProfile(configDir, profile, launchConfig);
const spawnError = await waitForImmediateSpawnError(launch.child, 500);
if (spawnError) {
throw new Error(`Failed to open Claude App: ${spawnError}`);
}
process.stdout.write(`Opened Claude App with ${profile.name || profile.id}.\n`);
return;
}
if (profile.agent === "zcode" && resolvedSurface === "app" && profileOptions.agentArgs.length === 0) {
const launch = launchZcodeAppProfile(configDir, profile, launchConfig);
const spawnError = await waitForImmediateSpawnError(launch.child, 500);
if (spawnError) {
throw new Error(`Failed to open ZCode App: ${spawnError}`);
}
process.stdout.write(`Opened ZCode App with ${profile.name || profile.id}.\n`);
return;
}
const plan = buildProfileLaunchPlan(configDir, profile, resolvedSurface, profileOptions.agentArgs);
if (path.isAbsolute(plan.command) && !existsSync(plan.command)) {
throw new Error(`Profile launcher was not found: ${plan.command}. Open CCR once or re-save the profile.`);
}
const childEnv = {
...process.env,
...plan.env,
...botGatewayProfileEnv(launchConfig, profile, resolvedSurface)
};
delete childEnv.ELECTRON_RUN_AS_NODE;
View on GitHub (pinned to 99f24806c6)