{"record":{"id":"8e6dc2c73896b1dc","repo":"different-ai/openwork","slug":"cdp-target-list-failed-http-response-status","errorCode":null,"errorMessage":"CDP target list failed: HTTP ${response.status}","messagePattern":"CDP target list failed: HTTP (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"apps/desktop/electron/browser-panel.mjs","lineNumber":128,"sourceCode":"      console.warn(\"[browser] failed to route blocked main-window navigation\", error);\n    });\n  }\n\n  function cdpBrowserUrl() {\n    return `http://127.0.0.1:${remoteDebugPort}`;\n  }\n\n  function browserTargetMarkerUrl(tabId) {\n    const marker = `openwork-browser-tab:${tabId}`;\n    const html = `<!doctype html><title>${marker}</title><meta name=\"openwork-browser-tab\" content=\"${tabId}\"><body>${marker}</body>`;\n    return `data:text/html;charset=utf-8,${encodeURIComponent(html)}`;\n  }\n\n  async function listCdpTargets() {\n    if (!remoteDebugPort || remoteDebugPort <= 0) return [];\n    // loopback-fetch: CDP discovery targets Electron's local remote debugging port on 127.0.0.1.\n    const response = await fetch(`${cdpBrowserUrl()}/json/list`, { signal: AbortSignal.timeout(1000) });\n    if (!response.ok) throw new Error(`CDP target list failed: HTTP ${response.status}`);\n    const targets = await response.json();\n    return Array.isArray(targets) ? targets : [];\n  }\n\n  async function resolveBrowserCdpTargetId(tabId) {\n    const marker = encodeURIComponent(`openwork-browser-tab:${tabId}`);\n    const deadline = Date.now() + BROWSER_TARGET_RESOLVE_TIMEOUT_MS;\n    while (Date.now() < deadline) {\n      const targets = await listCdpTargets().catch(() => []);\n      const target = targets.find((candidate) => (\n        candidate?.type === \"page\" &&\n        typeof candidate.id === \"string\" &&\n        typeof candidate.url === \"string\" &&\n        candidate.url.includes(marker)\n      ));\n      if (target?.id) return target.id;\n      await new Promise((resolve) => setTimeout(resolve, BROWSER_TARGET_RESOLVE_INTERVAL_MS));\n    }","sourceCodeStart":110,"sourceCodeEnd":146,"githubUrl":"https://github.com/different-ai/openwork/blob/2b7df46e8ae1517d64c896c7793d2d52ec845669/apps/desktop/electron/browser-panel.mjs#L110-L146","documentation":"listCdpTargets queries Electron's local Chrome DevTools Protocol endpoint (`/json/list` on the 127.0.0.1 remote-debugging port) to enumerate debuggable targets. Any non-OK HTTP status (404, 503, connection rejected at HTTP layer after fetch succeeds) raises this error with the status code embedded. The call is bounded by a 1s AbortSignal.timeout.","triggerScenarios":"fetch to `${cdpBrowserUrl()}/json/list` returned response.ok === false — remote-debugging port not serving CDP, wrong port, devtools disabled in this Electron build, or the endpoint temporarily unavailable during startup/shutdown.","commonSituations":"App launched without --remote-debugging-port so the port probes wrong service; Electron started but CDP not yet listening; security software proxying the loopback port; remoteDebugPort configured from a stale value after restart.","solutions":["Verify the app was launched with a valid --remote-debugging-port and that remoteDebugPort matches it","Retry after a short delay if the app/CDP server is still starting","curl http://127.0.0.1:<port>/json/list to confirm the endpoint responds","Handle non-OK statuses gracefully upstream (return [] instead of throwing) if target discovery is best-effort"],"exampleFix":"// before\nconst response = await fetch(`${cdpBrowserUrl()}/json/list`, { signal: AbortSignal.timeout(1000) });\nif (!response.ok) throw new Error(`CDP target list failed: HTTP ${response.status}`);\n// after: tolerate transient unavailability\nconst response = await fetch(`${cdpBrowserUrl()}/json/list`, { signal: AbortSignal.timeout(1000) });\nif (!response.ok) return []; // treat as \"no targets yet\" and let caller retry","handlingStrategy":"fallback","validationCode":"// Probe CDP before relying on target discovery\nconst probe = await fetch(`${cdpBrowserUrl()}/json/version`, { signal: AbortSignal.timeout(1000) }).catch(() => null);\nconst cdpReady = probe?.ok === true;","typeGuard":null,"tryCatchPattern":"try {\n  const targets = await listCdpTargets();\n} catch (err) {\n  if (String(err.message).startsWith(\"CDP target list failed:\")) {\n    // CDP not ready or disabled; degrade gracefully and retry with backoff\n    await sleep(500);\n    const targets = await listCdpTargets().catch(() => []);\n  }\n}","preventionTips":["Launch Electron with a real --remote-debugging-port and keep remoteDebugPort in sync","Retry /json/list with short backoff during app startup","curl http://127.0.0.1:<port>/json/list when diagnosing port/proxy issues","Treat target discovery as best-effort: return [] on non-OK instead of failing the panel"],"tags":["cdp","devtools","http","electron"],"backgroundTag":"cdp-target-list-failed","analyzedSha":"2b7df46e8ae1517d64c896c7793d2d52ec845669","analyzedAt":"2026-09-01T07:59:23.713Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}