{"record":{"id":"27e1a396dfe500b8","repo":"deepseek-ai/deepseek-harness","slug":"transport-failure-for-channel-endpoint-http","errorCode":null,"errorMessage":"transport failure for ${channel}/${endpoint}: HTTP ${response.status}","messagePattern":"transport failure for (.+?)/(.+?): HTTP (.+?)","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/client/connection/src/client/rpc.ts","lineNumber":45,"sourceCode":"      assertTarget(channel, endpoint)\n      const rpcId = RpcId(randomUuid())\n      const message: ClientRequest = {\n        type: 'client-request',\n        rpcId,\n        method: endpoint,\n        payload,\n      }\n      const response = await send(\n        new URL(`${channel}/${endpoint}`, resolveBase()),\n        {\n          method: 'POST',\n          headers: { 'content-type': 'application/json' },\n          body: JSON.stringify(message),\n          ...signal === undefined ? {} : { signal },\n        },\n      )\n      if (!response.ok) {\n        throw new Error(`transport failure for ${channel}/${endpoint}: HTTP ${response.status}`)\n      }\n      const full = serverResponseSchema.parse(await response.json())\n      if (full.rpcId !== rpcId) {\n        throw new Error(`rpcId mismatch for ${endpoint}: sent ${rpcId}, got ${full.rpcId}`)\n      }\n      return full.result\n    },\n  }\n}\n\nfunction resolveBase(): string {\n  const location = (globalThis as { location?: { origin?: string } }).location\n  return location?.origin !== undefined && location.origin !== 'null' ? location.origin : INTERNAL_BASE\n}\n\nfunction assertTarget(channel: string, endpoint: string): void {\n  const segments = endpoint.split('/')\n  if (!CHANNEL_PATTERN.test(channel)","sourceCodeStart":27,"sourceCodeEnd":63,"githubUrl":"https://github.com/deepseek-ai/deepseek-harness/blob/b150a551b8d465e31e418e1b2eaf5e79bbb7d28e/packages/client/connection/src/client/rpc.ts#L27-L63","documentation":"The browser RPC caller (createWebConnectionRpc.call) posts a JSON client-request envelope to ${origin}${channel}/${endpoint} and throws this error whenever the HTTP response is not ok, embedding the status. The status separates the trust fence (403: the request Host is neither loopback nor declared in trustedHosts), unregistered targets (404), bodies over maxRequestBodyBytes (413), and handler faults (5xx).","triggerScenarios":"A browser-side rpc.call(channel, endpoint, payload) answered 403 when the GUI is reached through an undeclared authority, 404 for an unregistered channel/endpoint, 413 when the body exceeds maxRequestBodyBytes, or 5xx when the handler throws server-side.","commonSituations":"Accessing the GUI via an undeclared hostname or reverse proxy after binding 0.0.0.0; a service worker or proxy intercepting /api; typo'd channel or endpoint strings; image-heavy payloads crossing the body cap.","solutions":["403: open the GUI via loopback, or declare the serving authority in trustedHosts so the Host fence accepts it","404: check the channel and endpoint strings against the registered RPC handlers","413: raise client-connection maxRequestBodyBytes (staying above the image-limit floor) or shrink the payload","5xx: read the dsh server logs for the handler stack trace"],"exampleFix":"// before\nconst result = await rpc.call('/connection', 'session.create', payload)\n\n// after — branch on the embedded status\ntry {\n  const result = await rpc.call('/connection', 'session.create', payload)\n} catch (error) {\n  const status = Number(/HTTP (\\d+)$/.exec(String(error))?.[1] ?? 0)\n  if (status === 403) throw new Error('authority not trusted; use the loopback URL or declare trustedHosts')\n  if (status === 413) throw new Error('payload exceeds maxRequestBodyBytes')\n  throw error\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  const result = await rpc.call(channel, endpoint, payload)\n} catch (error) {\n  const status = Number(/HTTP (\\d+)$/.exec(String(error))?.[1] ?? 0)\n  if (status === 403) redirectToListedUrl()   // trust fence\n  else if (status === 413) shrinkPayload()\n  else if (status >= 500) reportServerFault(error)\n  else throw error\n}","preventionTips":["Enter the GUI only through the URL dsh web prints","Declare every non-loopback serving name in trustedHosts","Keep request bodies under maxRequestBodyBytes and keep caching layers off /api"],"tags":["http","rpc","network","status-code","trust-fence"],"backgroundTag":"http-request-failed","analyzedSha":"b150a551b8d465e31e418e1b2eaf5e79bbb7d28e","analyzedAt":"2026-08-24T18:12:29.105Z","schemaVersion":2},"datasetVersion":"2026-08-24T22:17:12.610Z"}