can1357/oh-my-pi · error
Internal TLS bridge did not bind to a TCP address
Error message
Internal TLS bridge did not bind to a TCP address
What it means
After the internal TLS bridge server listens on an ephemeral port, the code reads tlsServer.address() and requires a TCP AddressInfo object. If Node returns null (server not actually listening) or a string (bound to a Unix socket/pipe), the bridge cannot be connected to via TCP, so it closes the server and throws this error. It is a defensive invariant against unexpected socket binding behavior.
Source
Thrown at packages/coding-agent/src/cli/claude-trace-cli.ts:612
}
async #openMitmTunnelAsync(socket: net.Socket, target: ConnectTarget, rest: Buffer): Promise<void> {
const clientReady = Promise.withResolvers<tls.TLSSocket>();
const tlsServer = tls.createServer(
{ cert: CLAUDE_TRACE_DEBUG_CERT, key: CLAUDE_TRACE_DEBUG_KEY, ALPNProtocols: ["http/1.1"] },
clientTls => {
this.#track(clientTls);
clientReady.resolve(clientTls);
},
);
tlsServer.once("error", error => clientReady.reject(error));
const listening = Promise.withResolvers<void>();
tlsServer.listen(0, DEFAULT_PROXY_HOST, () => listening.resolve());
await listening.promise;
const address = tlsServer.address();
if (!address || typeof address === "string") {
tlsServer.close();
throw new Error("Internal TLS bridge did not bind to a TCP address");
}
const bridge = this.#track(net.connect({ host: DEFAULT_PROXY_HOST, port: address.port }));
const connected = Promise.withResolvers<void>();
bridge.once("connect", () => connected.resolve());
bridge.once("error", error => connected.reject(error));
await connected.promise;
socket.pipe(bridge);
bridge.pipe(socket);
const closeInternalServer = () => tlsServer.close();
socket.once("close", closeInternalServer);
bridge.once("close", closeInternalServer);
if (rest.length > 0) bridge.write(rest);
const clientTls = await clientReady.promise;
const upstreamTls = this.#track(
tls.connect({
host: target.host,
port: target.port,
servername: net.isIP(target.host) ? undefined : target.host,View on GitHub (pinned to 9690622007)
Solutions
- Check that no other code path closes tlsServer before the bridge connect completes (look for close() calls racing startup).
- Ensure DEFAULT_PROXY_HOST (127.0.0.1) is bindable — verify no sandbox/firewall blocks loopback binding.
- Re-run the trace; if transient, add a small delay or await the actual 'listening' event carrying the address rather than a detached resolver.
- If instrumented (e.g. monkey-patched net/tls in tests), restore the unpatched modules before starting the bridge.
Example fix
// before
const address = tlsServer.address();
if (!address || typeof address === "string") { throw new Error("..."); }
// after: wait for the listen callback to supply the port directly
tlsServer.listen(0, DEFAULT_PROXY_HOST, () => listening.resolve());
// ...and in the callback capture: const address = tlsServer.address() as net.AddressInfo; port = address.port; Defensive patterns
Strategy: type-guard
Type guard
function isAddressInfo(a: ReturnType<typeof tls.Server.prototype.address> | null): a is net.AddressInfo {
return !!a && typeof a === "object" && typeof (a as net.AddressInfo).port === "number";
}
// usage: if (!isAddressInfo(tlsServer.address())) { tlsServer.close(); throw ... } Try / catch
try {
await startTlsBridge();
} catch (err) {
if (err instanceof Error && err.message === "Internal TLS bridge did not bind to a TCP address") {
// retry once after cleanup / fall back to external proxy
} else throw err;
} Prevention
- Don't close the bridge server concurrently with startup; serialize shutdown after connect completes
- Avoid monkey-patching net/tls in the same process as the trace
- Verify loopback (127.0.0.1) binding is permitted in the sandbox/container before running
When it happens
Trigger: tlsServer.address() returns null or a string right after the 'listening' event resolves — e.g. the server closed concurrently, the runtime bound it to a non-TCP handle, or another component closed/replaced the server between listen and address().
Common situations: Running under an environment that intercepts or patches net/tls servers (instrumentation, test harnesses); a race where shutdown logic closes the bridge while startup is still in flight; exotic platforms where localhost binding behaves differently.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- Proxy tunnel aborted
- ${errorMessage(first.error)}${outputSuffix()}
- Proxy configuration uses a scheme Bun's fetch cannot use${de
- timed out: {command}
- V2 remote compaction failed (${response.status} ${response.s
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/e6e862b5ac89610a.
Report an issue: GitHub.