vercel/ai · error · RelayRequestError
Host tool relay request is too large.
Error message
Host tool relay request is too large.
What it means
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.
Source
Thrown at packages/harness-acp/src/v1/bridge/host-tool-relay.ts:444
Object.keys(value)
.sort()
.filter(key => value[key] !== undefined)
.map(key => [key, canonicalizeJSON({ value: value[key] })]),
);
}
async function readJSONBody({
request,
}: {
request: IncomingMessage;
}): Promise<unknown> {
const chunks: Buffer[] = [];
let size = 0;
for await (const chunk of request) {
const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
size += buffer.length;
if (size > 16 * 1024 * 1024) {
throw new RelayRequestError({
status: 413,
message: 'Host tool relay request is too large.',
});
}
chunks.push(buffer);
}
const text = Buffer.concat(chunks).toString('utf8');
try {
return await new Response(text, {
headers: { 'content-type': 'application/json' },
}).json();
} catch {
throw new RelayRequestError({
status: 400,
message: 'Host tool relay request is not valid JSON.',
});
}
}View on GitHub (pinned to 69428b1f8b)
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.
Example fix
// before
const result = { fileContents: await fs.readFile(hugeFile, 'utf8') };
await relay.callTool('read_file', result);
// after
const stat = await fs.stat(hugeFile);
const excerpt = (await fs.readFile(hugeFile, 'utf8')).slice(0, 100_000);
await relay.callTool('read_file', { size: stat.size, excerpt }); Defensive patterns
Strategy: validation
Validate before calling
function isWithinRelayLimit(payload: unknown): boolean {
return Buffer.byteLength(JSON.stringify(payload), 'utf8') <= 16 * 1024 * 1024;
}
if (!isWithinRelayLimit(toolCall)) throw new Error('Relay payload exceeds 16 MiB'); Try / catch
try {
await relay.callTool(name, args);
} catch (error) {
if (RelayRequestError.isInstance(error) && error.status === 413) {
// shrink/paginate the payload and retry
}
throw error;
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Failed to fetch the response.
- The response body is empty.
- ${readErrorMessage({ value, status: response.status })}
- Unknown host tool relay endpoint.
- Invalid host tool relay credential.
AI-assisted analysis of vercel/ai@69428b1f8b (2026-08-30).
Data as JSON: /api/errors/c74ed7d5ba9a5239.
Report an issue: GitHub.