{"record":{"id":"e6e862b5ac89610a","repo":"can1357/oh-my-pi","slug":"internal-tls-bridge-did-not-bind-to-a-tcp-address","errorCode":null,"errorMessage":"Internal TLS bridge did not bind to a TCP address","messagePattern":"Internal TLS bridge did not bind to a TCP address","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/cli/claude-trace-cli.ts","lineNumber":612,"sourceCode":"\t}\n\n\tasync #openMitmTunnelAsync(socket: net.Socket, target: ConnectTarget, rest: Buffer): Promise<void> {\n\t\tconst clientReady = Promise.withResolvers<tls.TLSSocket>();\n\t\tconst tlsServer = tls.createServer(\n\t\t\t{ cert: CLAUDE_TRACE_DEBUG_CERT, key: CLAUDE_TRACE_DEBUG_KEY, ALPNProtocols: [\"http/1.1\"] },\n\t\t\tclientTls => {\n\t\t\t\tthis.#track(clientTls);\n\t\t\t\tclientReady.resolve(clientTls);\n\t\t\t},\n\t\t);\n\t\ttlsServer.once(\"error\", error => clientReady.reject(error));\n\t\tconst listening = Promise.withResolvers<void>();\n\t\ttlsServer.listen(0, DEFAULT_PROXY_HOST, () => listening.resolve());\n\t\tawait listening.promise;\n\t\tconst address = tlsServer.address();\n\t\tif (!address || typeof address === \"string\") {\n\t\t\ttlsServer.close();\n\t\t\tthrow new Error(\"Internal TLS bridge did not bind to a TCP address\");\n\t\t}\n\t\tconst bridge = this.#track(net.connect({ host: DEFAULT_PROXY_HOST, port: address.port }));\n\t\tconst connected = Promise.withResolvers<void>();\n\t\tbridge.once(\"connect\", () => connected.resolve());\n\t\tbridge.once(\"error\", error => connected.reject(error));\n\t\tawait connected.promise;\n\t\tsocket.pipe(bridge);\n\t\tbridge.pipe(socket);\n\t\tconst closeInternalServer = () => tlsServer.close();\n\t\tsocket.once(\"close\", closeInternalServer);\n\t\tbridge.once(\"close\", closeInternalServer);\n\t\tif (rest.length > 0) bridge.write(rest);\n\t\tconst clientTls = await clientReady.promise;\n\t\tconst upstreamTls = this.#track(\n\t\t\ttls.connect({\n\t\t\t\thost: target.host,\n\t\t\t\tport: target.port,\n\t\t\t\tservername: net.isIP(target.host) ? undefined : target.host,","sourceCodeStart":594,"sourceCodeEnd":630,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/cli/claude-trace-cli.ts#L594-L630","documentation":"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.","triggerScenarios":"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().","commonSituations":"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.","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."],"exampleFix":"// before\nconst address = tlsServer.address();\nif (!address || typeof address === \"string\") { throw new Error(\"...\"); }\n// after: wait for the listen callback to supply the port directly\ntlsServer.listen(0, DEFAULT_PROXY_HOST, () => listening.resolve());\n// ...and in the callback capture: const address = tlsServer.address() as net.AddressInfo; port = address.port;","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"function isAddressInfo(a: ReturnType<typeof tls.Server.prototype.address> | null): a is net.AddressInfo {\n  return !!a && typeof a === \"object\" && typeof (a as net.AddressInfo).port === \"number\";\n}\n// usage: if (!isAddressInfo(tlsServer.address())) { tlsServer.close(); throw ... }","tryCatchPattern":"try {\n  await startTlsBridge();\n} catch (err) {\n  if (err instanceof Error && err.message === \"Internal TLS bridge did not bind to a TCP address\") {\n    // retry once after cleanup / fall back to external proxy\n  } else throw err;\n}","preventionTips":["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"],"tags":["tls","network","proxy","nodejs"],"backgroundTag":"tls-bind-failure","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}