Mintplex-Labs/anything-llm · error · Error

No webSocketDebuggerUrl — is Chromium running?

Error message

No webSocketDebuggerUrl — is Chromium running?

What it means

Thrown by the cdp-eval helper when GET http://127.0.0.1:9222/json/version returns JSON whose webSocketDebuggerUrl field is missing/empty. That field is only present when the HTTP endpoint is a real Chrome DevTools debugger service; its absence means something answered on port 9222 but it is not a Chromium instance started with remote debugging enabled (or it is a headless shell/older build that omits the browser-level WS URL). The helper needs the browser WS endpoint to send Target.getTargets/attachToTarget.

Solutions

  1. Relaunch Chromium with remote debugging: chromium --remote-debugging-port=9222 --user-data-dir=/tmp/oc-chrome (Chrome 111+ requires a non-default --user-data-dir)
  2. Verify with curl http://127.0.0.1:9222/json/version that webSocketDebuggerUrl is present before retrying
  3. Free port 9222 from whatever else is listening (lsof -i :9222 / netstat) or start Chromium on a free port and update the helper
  4. Disable policies/flags (e.g. --remote-allow-origins=*) that strip the debugger WS endpoint in managed environments

Example fix

# before: plain launch, /json/version has no webSocketDebuggerUrl
chromium --no-sandbox &
# after
chromium --remote-debugging-port=9222 --user-data-dir=/tmp/oc-chrome --no-first-run &
curl -s http://127.0.0.1:9222/json/version | jq .webSocketDebuggerUrl
Defensive patterns

Strategy: validation

Validate before calling

async function cdpReady() {
  try {
    const v = JSON.parse(await (await fetch('http://127.0.0.1:9222/json/version')).text());
    return typeof v.webSocketDebuggerUrl === 'string' && v.webSocketDebuggerUrl.startsWith('ws');
  } catch { return false; }
}
if (!(await cdpReady())) { /* relaunch Chromium with --remote-debugging-port=9222 --user-data-dir=... */ }

Type guard

function hasDebuggerUrl(v: unknown): v is { webSocketDebuggerUrl: string } {
  return typeof (v as any)?.webSocketDebuggerUrl === 'string' && (v as any).webSocketDebuggerUrl.length > 0;
}

Try / catch

try { await evalInPage(expr); } catch (e) { if (/No webSocketDebuggerUrl/.test(e.message)) { await relaunchChromiumWithDebugPort(); await evalInPage(expr); } else throw e; }

Prevention

When it happens

Trigger: Chromium launched without --remote-debugging-port=9222 while another service occupies 9222 and returns JSON on /json/version; using chrome --headless=old variants or minimal shells that omit webSocketDebuggerUrl in /json/version; a DevTools-compatible proxy (e.g. chromedriver or a tab-capture server) that serves /json/version without the WS field.

Common situations: The open-computer agent expects its own pre-launched Chromium with remote debugging; users kill that instance and open Chrome normally, or another tool (browser extension host, devtools proxy) grabs 9222; corporate Chromium builds with remote debugging disabled by policy.

Related errors


AI-assisted analysis of Mintplex-Labs/anything-llm@3aec848f28 (2026-08-18). Data as JSON: /api/errors/17b2790631da45a7. Report an issue: GitHub.

Appendix: source

Thrown at open-computer/services/interface-service/utils/cdp-eval.js:71

      ws.off("message", handler);
      clearTimeout(timeout);
      if (parsed.error) {
        reject(new Error(`CDP error: ${parsed.error.message}`));
      } else {
        resolve(parsed.result);
      }
    }

    ws.on("message", handler);
    ws.send(JSON.stringify(msg));
  });
}

async function main() {
  const versionRaw = await httpGet("http://127.0.0.1:9222/json/version");
  const version = JSON.parse(versionRaw);
  const browserWsUrl = version.webSocketDebuggerUrl;
  if (!browserWsUrl) throw new Error("No webSocketDebuggerUrl — is Chromium running?");

  const ws = await new Promise((resolve, reject) => {
    const socket = new WebSocket(browserWsUrl);
    const t = setTimeout(() => reject(new Error("WS connect timeout")), 5000);
    socket.on("open", () => { clearTimeout(t); resolve(socket); });
    socket.on("error", (err) => { clearTimeout(t); reject(err); });
  });

  try {
    const { targetInfos } = await cdpSend(ws, "Target.getTargets");
    const pages = targetInfos.filter(
      (t) => t.type === "page" && !t.url.startsWith("chrome://") && !t.url.startsWith("devtools://")
    );
    if (pages.length === 0) throw new Error("No browser pages open.");

    let target = pages[pages.length - 1];
    if (targetUrl) {
      const match = pages.find(

View on GitHub (pinned to 3aec848f28)