musistudio/claude-code-router · error · Error
Failed to start MITM server for ${hostname}
Error message
Failed to start MITM server for ${hostname} What it means
The proxy service failed to bind a local MITM listener for a CONNECTed hostname. After calling listen(server, 0, "127.0.0.1"), server.address() returned null or a string (pipe name), which should not happen for a TCP listener, so the half-started server is closed and this error thrown.
Source
Thrown at packages/core/src/proxy/service.ts:690
const authority = this.authority ?? readProxyCertificateAuthority();
const certificate = createCertificateForHost(hostname, authority);
const server = https.createServer(
{
ALPNProtocols: ["http/1.1"],
cert: certificate.cert,
key: certificate.key
},
(request, response) => {
void this.handleProxyRequest(request, response, "https:").catch((error) => {
sendProxyError(response, 502, formatError(error));
});
}
);
await listen(server, 0, "127.0.0.1");
const address = server.address();
if (!address || typeof address === "string") {
await closeServer(server);
throw new Error(`Failed to start MITM server for ${hostname}`);
}
return {
host: hostname,
port: address.port,
server
};
}
private async handleProxyRequest(request: IncomingMessage, response: ServerResponse, defaultProtocol: "http:" | "https:"): Promise<void> {
if (!this.config) {
sendProxyError(response, 503, "Proxy service is not configured.");
return;
}
const requestId = randomUUID();
const targetUrl = resolveRequestUrl(request, defaultProtocol);
const pluginRoute = pluginService.resolveProxyRoute(targetUrl);
if (!pluginRoute && isCursorAgentProxyRequest(targetUrl)) {View on GitHub (pinned to 99f24806c6)
Solutions
- Retry the CONNECT request (transient bind failure) after a short delay
- Raise fd/ephemeral port limits (ulimit -n, net.ipv4.ip_local_port_range) if many tunnels are open
- Reduce concurrent MITM connections or reuse the existing MITM server for that hostname
- Inspect system-level socket exhaustion (ss -s, lsof) if it persists
Example fix
// before
const mitm = await proxy.getMitmServer(hostname); // throws
// after
import { retry } from "./retry";
const mitm = await retry(() => proxy.getMitmServer(hostname), { attempts: 3, backoffMs: 200 }); Defensive patterns
Strategy: retry
Try / catch
try { return await withMitm(hostname); } catch (e) { if (e.message.includes("Failed to start MITM server")) return await delayThenRetry(200, () => withMitm(hostname)); throw e; } Prevention
- Bound concurrent CONNECT tunnels per process
- Monitor ephemeral port and fd usage
- Retry transient bind failures with backoff
When it happens
Trigger: CONNECT tunneling to a hostname when the ephemeral 127.0.0.1 listener fails to yield an inet address: address exhaustion (no free ports), file descriptor limits, or an unexpected server state where address() is null right after listen.
Common situations: Heavy parallel CONNECT tunnels exhausting ephemeral ports or fd ulimit; embedded environment with restricted networking; races where the server closes immediately after listen.
Related errors
AI-assisted analysis of musistudio/claude-code-router@99f24806c6 (2026-08-27).
Data as JSON: /api/errors/c92c866db9e63a6b.
Report an issue: GitHub.