{"record":{"id":"c74ed7d5ba9a5239","repo":"vercel/ai","slug":"host-tool-relay-request-is-too-large","errorCode":null,"errorMessage":"Host tool relay request is too large.","messagePattern":"Host tool relay request is too large\\.","errorType":"http","errorClass":"RelayRequestError","httpStatus":413,"severity":"error","filePath":"packages/harness-acp/src/v1/bridge/host-tool-relay.ts","lineNumber":444,"sourceCode":"    Object.keys(value)\n      .sort()\n      .filter(key => value[key] !== undefined)\n      .map(key => [key, canonicalizeJSON({ value: value[key] })]),\n  );\n}\n\nasync function readJSONBody({\n  request,\n}: {\n  request: IncomingMessage;\n}): Promise<unknown> {\n  const chunks: Buffer[] = [];\n  let size = 0;\n  for await (const chunk of request) {\n    const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);\n    size += buffer.length;\n    if (size > 16 * 1024 * 1024) {\n      throw new RelayRequestError({\n        status: 413,\n        message: 'Host tool relay request is too large.',\n      });\n    }\n    chunks.push(buffer);\n  }\n  const text = Buffer.concat(chunks).toString('utf8');\n  try {\n    return await new Response(text, {\n      headers: { 'content-type': 'application/json' },\n    }).json();\n  } catch {\n    throw new RelayRequestError({\n      status: 400,\n      message: 'Host tool relay request is not valid JSON.',\n    });\n  }\n}","sourceCodeStart":426,"sourceCodeEnd":462,"githubUrl":"https://github.com/vercel/ai/blob/69428b1f8b037e4d118fb4853428d5c4e620493c/packages/harness-acp/src/v1/bridge/host-tool-relay.ts#L426-L462","documentation":"The host tool relay HTTP server reads the entire request body in readJSONBody and rejects any body larger than 16 MiB, responding with HTTP 413 via RelayRequestError. The relay is the local endpoint the ACP harness exposes so the agent process can call back into host-side MCP tools, so payloads are expected to stay small. This guard prevents unbounded memory use when a caller streams an oversized or runaway request.","triggerScenarios":"Any POST to the local host tool relay endpoint whose request body accumulates more than 16 * 1024 * 1024 bytes while readJSONBody iterates over the IncomingMessage stream, typically when a tool call sends huge arguments or tool results back through the relay.","commonSituations":"A tool implementation returning a very large result (big file contents, base64 blobs) that is relayed as the tool call payload; a misbehaving client retrying with the whole conversation embedded per call; accidental posting of binary or non-streamed data instead of a compact JSON envelope.","solutions":["Reduce the size of the tool call arguments or results being sent to the relay (truncate or page large data, pass references instead of inline content).","Check for accidental duplication of large payloads across looped tool calls and send only the delta.","If you legitimately need larger payloads, host the tool call path outside the relay or chunk the data across multiple calls."],"exampleFix":"// before\nconst result = { fileContents: await fs.readFile(hugeFile, 'utf8') };\nawait relay.callTool('read_file', result);\n// after\nconst stat = await fs.stat(hugeFile);\nconst excerpt = (await fs.readFile(hugeFile, 'utf8')).slice(0, 100_000);\nawait relay.callTool('read_file', { size: stat.size, excerpt });","handlingStrategy":"validation","validationCode":"function isWithinRelayLimit(payload: unknown): boolean {\n  return Buffer.byteLength(JSON.stringify(payload), 'utf8') <= 16 * 1024 * 1024;\n}\nif (!isWithinRelayLimit(toolCall)) throw new Error('Relay payload exceeds 16 MiB');","typeGuard":null,"tryCatchPattern":"try {\n  await relay.callTool(name, args);\n} catch (error) {\n  if (RelayRequestError.isInstance(error) && error.status === 413) {\n    // shrink/paginate the payload and retry\n  }\n  throw error;\n}","preventionTips":["Keep tool arguments and results small; pass references or file paths instead of inlining large content.","Estimate payload size with Buffer.byteLength(JSON.stringify(...)) before sending.","Never echo whole files or conversation history through each relay call."],"tags":["http","payload-size","limit-exceeded"],"backgroundTag":"http-413-payload-too-large","analyzedSha":"69428b1f8b037e4d118fb4853428d5c4e620493c","analyzedAt":"2026-08-30T12:32:21.016Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}