musistudio/claude-code-router · error

Codex App DevTools port was not available${lastError ? `: ${

Error message

Codex App DevTools port was not available${lastError ? `: ${redactBridgeError(lastError)}` : "."}

What it means

waitForCodexDevToolsPort polls the Codex App's DevToolsActivePort file/socket until a timeout and throws this when no valid CDP port was obtained. The message includes the redacted last underlying error (redactBridgeError) explaining why each poll failed, or '.' when there was no specific error.

Source

Thrown at packages/core/src/agents/codex/media-preview-bridge.ts:242

  }
}

async function waitForCodexDevToolsPort(userDataDir: string, timeoutMs: number, stopped: () => boolean): Promise<number> {
  const file = path.join(userDataDir, codexDevToolsActivePortFile);
  const deadline = Date.now() + timeoutMs;
  let lastError: unknown;
  while (!stopped() && Date.now() < deadline) {
    try {
      const firstLine = readFileSync(file, "utf8").split(/\r?\n/, 1)[0]?.trim();
      const port = Number(firstLine);
      if (Number.isInteger(port) && port > 0 && port <= 65535) return port;
      lastError = new Error("DevToolsActivePort did not contain a valid port.");
    } catch (error) {
      lastError = error;
    }
    await sleep(codexMediaPreviewPollIntervalMs);
  }
  throw new Error(`Codex App DevTools port was not available${lastError ? `: ${redactBridgeError(lastError)}` : "."}`);
}

async function waitForCodexPageTarget(port: number, timeoutMs: number, stopped: () => boolean): Promise<DevToolsTarget> {
  const deadline = Date.now() + timeoutMs;
  let lastError: unknown;
  while (!stopped() && Date.now() < deadline) {
    try {
      const response = await fetch(`http://127.0.0.1:${port}/json/list`, {
        redirect: "error",
        signal: AbortSignal.timeout(1_000)
      });
      if (!response.ok) throw new Error(`CDP target discovery returned HTTP ${response.status}.`);
      const targets = await response.json() as DevToolsTarget[];
      const pages = targets.filter((target) => target.type === "page" && target.webSocketDebuggerUrl);
      const target = pages.find(isCodexAppPageTarget) || pages.find((entry) => (entry.url || "").startsWith("app://"));
      if (target) return target;
    } catch (error) {
      lastError = error;

View on GitHub (pinned to 99f24806c6)

Solutions

  1. Verify the Codex App is actually running and was launched with DevTools/CDP enabled
  2. Increase the timeout argument passed to waitForCodexDevToolsPort for slow startups
  3. Read the redacted lastError in the message to identify the underlying cause (file missing vs invalid port) and fix that (permissions, correct user-data-dir)
  4. Retry the bridge start after the app has fully booted

Example fix

// before
const port = await waitForCodexDevToolsPort(3000, () => false);
// after
const port = await waitForCodexDevToolsPort(30000, () => false); // longer timeout, app started first
Defensive patterns

Strategy: retry

Validate before calling

// before bridging, confirm the DevToolsActivePort file exists and parses
import { existsSync, readFileSync } from 'node:fs';
function devToolsPortReady(path: string): boolean {
  try { const [port] = readFileSync(path, 'utf8').trim().split('\n'); return /^\d+$/.test(port); }
  catch { return false; }
}

Type guard

null

Try / catch

try { const port = await waitForCodexDevToolsPort(timeoutMs, stopped); } catch (e) { if (e instanceof Error && e.message.includes('DevTools port was not available')) { /* relaunch app with debugging enabled, retry with backoff */ } else throw e; }

Prevention

When it happens

Trigger: Starting the media preview bridge while the Codex desktop app is not running, was launched without remote debugging enabled, crashed during startup, or when the DevToolsActivePort file is missing/contains a non-numeric port, and the poll deadline expires.

Common situations: Codex app not installed or not launched; app launched without the --remote-debugging-port/DevTools flags; slow machine where startup exceeds the configured timeout; sandboxed environment where the DevTools port file isn't readable.

Related errors


AI-assisted analysis of musistudio/claude-code-router@99f24806c6 (2026-08-27). Data as JSON: /api/errors/e56a98c69ac5522e. Report an issue: GitHub.