{"record":{"id":"5c46512dad56f739","repo":"vercel/ai","slug":"the-claude-code-harness-requires-an-explicit-port-5c4651","errorCode":null,"errorMessage":"The Claude Code harness requires an explicit `portEndpoint` when using a basic sandbox session.","messagePattern":"The Claude Code harness requires an explicit `portEndpoint` when using a basic sandbox session\\.","errorType":"exception","errorClass":"HarnessCapabilityUnsupportedError","httpStatus":null,"severity":"error","filePath":"packages/harness-claude-code/src/claude-code-harness.ts","lineNumber":1230,"sourceCode":"function 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) {\n    throw new HarnessCapabilityUnsupportedError({\n      harnessId: 'claude-code',\n      message:\n        'The Claude Code harness requires an explicit `port` when using a basic sandbox session.',\n    });\n  }\n  if (portEndpoint == null) {\n    throw new HarnessCapabilityUnsupportedError({\n      harnessId: 'claude-code',\n      message:\n        'The Claude Code harness requires an explicit `portEndpoint` when using a basic sandbox session.',\n    });\n  }\n}\n\nasync function resolveBridgeEndpoint({\n  sandboxSession,\n  override,\n  port,\n}: {\n  sandboxSession: HarnessV1NetworkSandboxSession | SandboxSession;\n  override: HarnessV1PortEndpoint | undefined;\n  port: number;\n}): Promise<HarnessV1PortEndpoint> {\n  if (override != null) return override;\n  if ('getPortEndpoint' in sandboxSession) {","sourceCodeStart":1212,"sourceCodeEnd":1248,"githubUrl":"https://github.com/vercel/ai/blob/69428b1f8b037e4d118fb4853428d5c4e620493c/packages/harness-claude-code/src/claude-code-harness.ts#L1212-L1248","documentation":"The Claude Code harness needs to connect to a bridge server over WebSocket inside the sandbox. When the provided sandbox session is a 'basic' one that does not implement `getPortEndpoint`, the harness cannot resolve an endpoint itself, so it demands an explicit `portEndpoint` in the createClaudeCode config. This fail-fast validation (validateBasicSandboxSettings) runs at creation time and throws HarnessCapabilityUnsupportedError instead of failing later at connection time.","triggerScenarios":"Calling createClaudeCode with a sandbox session lacking a `getPortEndpoint` method while `portEndpoint` is undefined (even if `port` is set). Caught by validateBasicSandboxSettings before the harness session is created.","commonSituations":"Using a custom or minimal SandboxSession implementation that only exposes `ports` but not `getPortEndpoint`; passing `port` but forgetting `portEndpoint`; upgrading the harness package where basic sandbox sessions are no longer auto-resolved.","solutions":["Pass an explicit `portEndpoint` in createClaudeCode options (e.g. `{ url: 'wss://host:port/path' }` for the bridge WebSocket).","Use a network sandbox session that implements `getPortEndpoint` so the endpoint can be derived from the port.","If your sandbox exposes ports, ensure both `port` and `portEndpoint` are provided together when using a basic session.","Check the harness README for the expected HarnessV1PortEndpoint shape and construct it from your sandbox's forwarded URL."],"exampleFix":"// before\nconst harness = createClaudeCode({ sandboxSession: basicSession, port: 8080 });\n// after\nconst harness = createClaudeCode({\n  sandboxSession: basicSession,\n  port: 8080,\n  portEndpoint: { url: 'wss://sandbox.example.com/8080/ws' },\n});","handlingStrategy":"validation","validationCode":"function canUseBasicSandbox(session, opts) {\n  const hasGetPortEndpoint = session && typeof session.getPortEndpoint === 'function';\n  return hasGetPortEndpoint || (opts.port != null && opts.portEndpoint != null);\n}\nif (!canUseBasicSandbox(sandboxSession, config)) {\n  throw new Error('Provide portEndpoint (and port) or use a network sandbox with getPortEndpoint');\n}","typeGuard":"function hasPortEndpoint(\n  s: SandboxSession,\n): s is SandboxSession & { getPortEndpoint: (a: { port: number; protocol: 'ws' }) => Promise<HarnessV1PortEndpoint> } {\n  return 'getPortEndpoint' in s && typeof (s as any).getPortEndpoint === 'function';\n}","tryCatchPattern":"try {\n  const harness = createClaudeCode({ sandboxSession, port, portEndpoint });\n} catch (e) {\n  if (HarnessCapabilityUnsupportedError.isInstance(e) && e.message.includes('portEndpoint')) {\n    // fall back to a network sandbox or set portEndpoint\n  }\n  throw e;\n}","preventionTips":["Always pair `port` with `portEndpoint` when using a basic sandbox session.","Prefer network sandbox sessions that implement getPortEndpoint.","Add a config sanity check before createClaudeCode in your bootstrap code.","Read the harness docs on basic vs network sandbox capabilities."],"tags":["configuration","sandbox","websocket","validation"],"backgroundTag":"missing-sandbox-port-endpoint","analyzedSha":"69428b1f8b037e4d118fb4853428d5c4e620493c","analyzedAt":"2026-08-30T12:32:21.016Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}