musistudio/claude-code-router · error · Error

CCR management service is unavailable. Make sure the CCR app

Error message

CCR management service is unavailable. Make sure the CCR app or ccr ui command is running, then retry.

What it means

Thrown by the web client bridge rpc() helper when a call to the CCR management web API returns HTTP 404, meaning the management endpoint is not being served. The bridge expects the CCR desktop app or the `ccr ui` CLI command to be running and exposing the API.

Source

Thrown at packages/ui/src/web-client-bridge.ts:34

    headers: {
      "content-type": "application/json",
      ...(webAuthToken ? { [webAuthHeader]: webAuthToken } : {})
    },
    method: "POST"
  });
  let payload: RpcResponse | undefined;
  try {
    payload = await response.json() as RpcResponse;
  } catch {
    payload = undefined;
  }
  if (!response.ok || !payload?.ok) {
    const message = payload && !payload.ok
      ? payload.error.message
      : response.status === 404
        ? "CCR management service is unavailable. Make sure the CCR app or ccr ui command is running, then retry."
        : `CCR web API failed with HTTP ${response.status}`;
    throw new Error(message);
  }
  return payload.value;
}

function trimTrailingUndefined(args: unknown[]): unknown[] {
  let end = args.length;
  while (end > 0 && args[end - 1] === undefined) {
    end -= 1;
  }
  return end === args.length ? args : args.slice(0, end);
}

function readWebAuthToken(): string {
  const tokenFromUrl = readWebAuthTokenFromUrl();
  if (tokenFromUrl) {
    writeStoredWebAuthToken(tokenFromUrl);
    return tokenFromUrl;
  }

View on GitHub (pinned to 99f24806c6)

Solutions

  1. Start the CCR app or run `ccr ui` and confirm the process is alive, then retry
  2. Reload the web UI so it reconnects to the currently running service
  3. Verify nothing (proxy, base path, firewall) is rewriting the API URL to a nonexistent route
  4. Restart the CCR service if it crashed mid-session
Defensive patterns

Strategy: retry

Validate before calling

// Before bridging, probe the management API:
const res = await fetch(managementBaseUrl, { method: "HEAD" }).catch(() => null);
if (!res || res.status === 404) { await startCcrUi(); /* then retry */ }

Try / catch

try { await bridge.selectPluginDirectory(dir); } catch (e) { if (e instanceof Error && e.message.includes("CCR management service is unavailable")) { await ensureCcrRunning(); return retry(); } throw e; }

Prevention

When it happens

Trigger: Any bridge call (e.g. selectPluginDirectory, applyClaudeAppGateway) when the CCR app / ccr ui process is not running, was restarted on a different port, or the UI was loaded from a URL where the /api routes are absent.

Common situations: Opening the web UI in a plain browser without starting `ccr ui`; the CCR backend crashed or exited while the UI tab stayed open; proxying/routing that strips the API path so requests hit a 404; version mismatch where the endpoint path changed.

Related errors


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