Mintplex-Labs/anything-llm · error

No webSocketDebuggerUrl — is Chromium running?

Error message

No webSocketDebuggerUrl — is Chromium running?

What it means

Identical guard to cdp-eval's, in the cdp-input helper (click/type/key injection): GET http://127.0.0.1:9222/json/version succeeded but the parsed JSON has no webSocketDebuggerUrl, so there is no browser-level WS endpoint to attach Input.* domains to. Something is serving /json/version on 9222, but it is not a fully remote-debuggable Chromium.

Solutions

  1. Restart Chromium with --remote-debugging-port=9222 and a dedicated --user-data-dir so the browser WS endpoint is exposed
  2. curl http://127.0.0.1:9222/json/version and confirm webSocketDebuggerUrl is non-empty before invoking click/type/key
  3. Find and stop the squatter on 9222 or move your debug port and update the helper's URL
  4. If a puppeteer/playwright session owns the browser, drive input through that session instead of this helper

Example fix

# before
chromium &            # no debugging endpoint -> error
# after
chromium --remote-debugging-port=9222 --user-data-dir=/tmp/oc-chrome https://example.com &
node cdp-input.js click 100 200
Defensive patterns

Strategy: validation

Validate before calling

async function cdpInputReady() {
  const v = await (await fetch('http://127.0.0.1:9222/json/version')).json();
  return Boolean(v.webSocketDebuggerUrl);
}
if (!(await cdpInputReady())) throw new Error('relaunch Chromium: --remote-debugging-port=9222 --user-data-dir=/tmp/oc-chrome');

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 sendInput('click', x, y); } catch (e) { if (/No webSocketDebuggerUrl/.test(e.message)) { await relaunchChromiumWithDebugPort(); await sendInput('click', x, y); } else throw e; }

Prevention

When it happens

Trigger: Chromium running without --remote-debugging-port while another DevTools-protocol-speaking service owns 9222; headless shells or embedded Chromium builds whose /json/version omits the browser WS URL; managed/enterprise Chromium with the debug WS endpoint stripped.

Common situations: The desktop agent's Chromium got replaced by the user's normal browser session; a chromedriver or puppeteer-connected Chrome already bound to 9222 with a single-client WS URL; port 9222 forwarded to a container that only implements part of the DevTools HTTP API.

Related errors


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

Appendix: source

Thrown at open-computer/services/interface-service/utils/cdp-input.js:77

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

function sleep(ms) {
  return new Promise((r) => setTimeout(r, ms));
}

// Randomized human-like delay between keystrokes
function keystrokeDelay() {
  return 30 + Math.floor(Math.random() * 60);
}

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 {
    // Find target page
    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.");

    // Determine target URL filter (always last arg if it doesn't look like a coordinate/text)
    let targetUrl = "";

View on GitHub (pinned to 3aec848f28)