{"record":{"id":"667d98e031e487a0","repo":"vercel/ai","slug":"the-claude-code-harness-needs-a-tcp-port-exposed-b","errorCode":null,"errorMessage":"The claude-code harness needs a TCP port exposed by the sandbox. Create the sandbox with `ports: [<port>]` or pass `createClaudeCode({ port })`.","messagePattern":"The claude-code harness needs a TCP port exposed by the sandbox\\. Create the sandbox with `ports: \\[<port>\\]` or pass `createClaudeCode\\((.+?)\\)`\\.","errorType":"exception","errorClass":"HarnessCapabilityUnsupportedError","httpStatus":null,"severity":"error","filePath":"packages/harness-claude-code/src/claude-code-harness.ts","lineNumber":1204,"sourceCode":"        mcpServers: settings.mcpServers,\n        supportsUserMessageResponses: () => supportsUserMessageResponses,\n      });\n    },\n  };\n}\n\nfunction resolveBridgePort({\n  sandboxSession,\n  override,\n}: {\n  sandboxSession: HarnessV1NetworkSandboxSession | SandboxSession;\n  override: number | undefined;\n}): number {\n  if (override !== undefined) return override;\n  if ('ports' in sandboxSession && sandboxSession.ports.length > 0) {\n    return sandboxSession.ports[0];\n  }\n  throw new HarnessCapabilityUnsupportedError({\n    harnessId: 'claude-code',\n    message:\n      'The claude-code harness needs a TCP port exposed by the sandbox. ' +\n      'Create the sandbox with `ports: [<port>]` or pass `createClaudeCode({ port })`.',\n  });\n}\n\nfunction validateBasicSandboxSettings({\n  sandboxSession,\n  port,\n  portEndpoint,\n}: {\n  sandboxSession: HarnessV1NetworkSandboxSession | SandboxSession;\n  port: number | undefined;\n  portEndpoint: HarnessV1PortEndpoint | undefined;\n}): void {\n  if ('getPortEndpoint' in sandboxSession) return;\n  if (port == null) {","sourceCodeStart":1186,"sourceCodeEnd":1222,"githubUrl":"https://github.com/vercel/ai/blob/69428b1f8b037e4d118fb4853428d5c4e620493c/packages/harness-claude-code/src/claude-code-harness.ts#L1186-L1222","documentation":"`resolveBridgePort` determines the TCP port the harness uses to reach the Claude Code bridge inside the sandbox: an explicit `port` override wins, otherwise the first port in `sandboxSession.ports` is used. When neither exists — no override and the sandbox exposes no ports — it throws `HarnessCapabilityUnsupportedError` (harnessId `claude-code`) telling you to expose a port.","triggerScenarios":"Calling `createClaudeCode({ sandboxSession })` (no `port` option) where the sandbox session's `ports` array is empty or absent, so there is no port to route bridge traffic through.","commonSituations":"Creating a sandbox without `ports: [<port>]` and forgetting the `port` option; a sandbox provider that allocates ports lazily so `ports` is empty at harness construction; typos like `port: 0` intending 'auto' (0 is falsy but `undefined`-checked, so check the actual provider semantics).","solutions":["Pass an explicit port: `createClaudeCode({ port: 3000 })` matching the port the agent listens on in the sandbox.","Recreate the sandbox with the port exposed, e.g. `createSandbox({ ports: [3000] })`, so `sandboxSession.ports[0]` exists.","Use a sandbox session that exposes `getPortEndpoint` (network sandbox session) so port resolution happens via the endpoint instead.","Verify with your sandbox provider how/when ports are allocated; ensure ports are declared at session creation time."],"exampleFix":"// before\nconst sandbox = await createSandbox({});\ncreateClaudeCode({ sandboxSession: sandbox });\n// after\nconst sandbox = await createSandbox({ ports: [3000] });\ncreateClaudeCode({ sandboxSession: sandbox }); // or add { port: 3000 }","handlingStrategy":"validation","validationCode":"function assertBridgePortResolvable(sandboxSession, port) {\n  if (port !== undefined) return;\n  const ports = sandboxSession && 'ports' in sandboxSession ? sandboxSession.ports : [];\n  if (!Array.isArray(ports) || ports.length === 0) {\n    throw new TypeError('Provide createClaudeCode({ port }) or create the sandbox with ports: [<port>]');\n  }\n}\nassertBridgePortResolvable(sandboxSession, settings.port);","typeGuard":"function sandboxExposesPorts(session) {\n  return typeof session === 'object' && session !== null &&\n    'ports' in session && Array.isArray(session.ports) && session.ports.length > 0;\n}","tryCatchPattern":"try {\n  return createClaudeCode({ sandboxSession, ...settings });\n} catch (err) {\n  if (err?.name === 'HarnessCapabilityUnsupportedError' && err.message.includes('TCP port exposed by the sandbox')) {\n    return createClaudeCode({ sandboxSession, port: DEFAULT_BRIDGE_PORT, ...settings });\n  }\n  throw err;\n}","preventionTips":["Always create sandboxes with ports: [<port>] when using Claude Code","Pass an explicit port in createClaudeCode settings as a fallback","Prefer network sandbox sessions with getPortEndpoint for automatic port resolution"],"tags":["sandbox","network","port","capability-unsupported","harness-claude-code"],"backgroundTag":"sandbox-port-not-exposed","analyzedSha":"69428b1f8b037e4d118fb4853428d5c4e620493c","analyzedAt":"2026-08-30T12:32:21.016Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}