{"record":{"id":"ccb82d890a5a0bea","repo":"musistudio/claude-code-router","slug":"deep-link-plugin-app-url-was-not-reachable-on-th","errorCode":null,"errorMessage":"[deep-link] Plugin app URL was not reachable on the running gateway; restarting gateway once. ${formatError(error)}","messagePattern":"\\[deep-link\\] Plugin app URL was not reachable on the running gateway; restarting gateway once\\. (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"packages/electron/src/main/deep-link.ts","lineNumber":197,"sourceCode":"      app.setAsDefaultProtocolClient(appDeepLinkProtocol);\n    } catch (error) {\n      console.warn(`[deep-link] Failed to register ${appDeepLinkProtocol} protocol: ${formatError(error)}`);\n    }\n  }\n}\n\nasync function ensurePluginAppUrlAvailable(config: AppConfig, appUrl: string, startedGateway: boolean): Promise<void> {\n  try {\n    await waitForPluginAppUrl(\n      appUrl,\n      startedGateway ? pluginAppStartupProbeTimeoutMs : pluginAppExistingGatewayProbeTimeoutMs\n    );\n    return;\n  } catch (error) {\n    if (startedGateway) {\n      throw error;\n    }\n    console.warn(`[deep-link] Plugin app URL was not reachable on the running gateway; restarting gateway once. ${formatError(error)}`);\n  }\n\n  const restartedStatus = await gatewayService.start(config);\n  if (restartedStatus.state !== \"running\") {\n    throw new Error(restartedStatus.lastError || \"CCR gateway did not restart.\");\n  }\n  await waitForPluginAppUrl(appUrl, pluginAppStartupProbeTimeoutMs);\n}\n\nasync function ensureClaudeDesignWindowCdpOptions(\n  config: AppConfig,\n  pluginId: string,\n  startedGateway: boolean\n): ReturnType<typeof loadClaudeDesignWindowCdpOptions> {\n  try {\n    return await loadClaudeDesignWindowCdpOptions(config, pluginId);\n  } catch (error) {\n    if (startedGateway) {","sourceCodeStart":179,"sourceCodeEnd":215,"githubUrl":"https://github.com/musistudio/claude-code-router/blob/99f24806c6a2c660b16e53e95211c517448a6c90/packages/electron/src/main/deep-link.ts#L179-L215","documentation":"The plugin app URL health check against the running CCR gateway failed, so the code logs a warning and restarts the gateway once as a recovery step. This indicates the gateway is up but not serving the expected plugin route.","triggerScenarios":"openPluginRequest fires, gatewayService reports already running (startedGateway=false), but fetching the plugin app URL throws or times out — e.g. stale gateway process serving an old build without the plugin route.","commonSituations":"Gateway binary upgraded while old process still running, plugin installed after gateway start, port occupied by a zombie process, or a slow gateway still initializing its route table.","solutions":["Let the automatic one-shot restart run; if it succeeds the error self-heals","Manually stop the gateway process and retry the deep link","Reinstall/redeploy the plugin so the gateway serves its route","Check gateway logs for route registration failures"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"const ok = await fetch(appUrl, { method: 'HEAD' }).then(r => r.ok).catch(() => false); if (!ok) await gatewayService.restart();","typeGuard":null,"tryCatchPattern":"catch (error) { if (!startedGateway) { warn; await restartGatewayOnce(); } else throw error; }","preventionTips":["Health-check the plugin URL before opening deep links","Start gateway before installing plugin deep links","Monitor gateway version drift"],"tags":["gateway","plugin","health-check","restart"],"backgroundTag":"service-health-check-failed","analyzedSha":"99f24806c6a2c660b16e53e95211c517448a6c90","analyzedAt":"2026-08-27T04:11:01.184Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}