RPC error HTTP 413: Request body over the 64 KiB limit
Last updated:
At a glance
| Property | Value |
|---|---|
| Applies to | Every network, HTTP and WebSocket |
| HTTP status | 413 |
| error values | batch_too_large (array), request_too_large (object) |
| Limit | 64 KiB; 4 MiB on Robinhood Chain |
| Raised by plan | No: identical for every key |
| Counts whitespace | Yes: the limit is on the raw body |
| Standard name | RFC 9110 calls 413 Content Too Large |
Cause
Every JSON-RPC element is gated by method and plan, so the gateway has to read the whole body before forwarding it. It reads up to 64 KiB, or 4 MiB on Robinhood Chain, and whitespace counts. A body above that cannot be inspected safely, so it is refused rather than passed on unchecked. The usual cause is a batch built by an indexer or a multicall helper that grew with its input: the code works in tests and starts failing when a real block arrives with more receipts or logs to fetch.
Solution
- Check the
errorfield:batch_too_largefor an array body,request_too_largefor a single JSON-RPC object. - Split the batch into smaller arrays and send them one after another. Measure the serialized size in bytes, not the element count.
- Remove what you do not need from the body: long
eth_getLogsaddress lists are a common way to fill 64 KiB with a single element. - Use a method that returns a block's data in one call where the network offers one, such as
eth_getBlockReceipts, instead of one element per transaction.
Split by bytes
A count-based chunker is what breaks here: 500 small elements fit and 500 large ones do not. Build chunks against a byte budget, leaving headroom for the array brackets and commas.
const LIMIT = 60 * 1024; // stay under 64 KiB
const chunks = [[]];
let size = 2;
for (const call of calls) {
const bytes = new TextEncoder().encode(JSON.stringify(call)).length + 1;
if (size + bytes > LIMIT) { chunks.push([]); size = 2; }
chunks.at(-1).push(call);
size += bytes;
}When a batch is the wrong shape
If you keep hitting this while reading whole blocks, the batch may be the wrong tool. On Solana, a filtered Yellowstone gRPC stream delivers what you would otherwise poll for. On EVM networks, eth_getLogs with a narrow topic filter usually replaces a batch of per-transaction receipt reads.
Example
{
"error": "batch_too_large",
"message": "Batch body exceeds the 64 KiB inspection limit; split the batch into smaller requests",
"chain": "base"
}FAQ
- How many requests fit in 64 KiB?
- It depends on the serialized size of each element. A bare eth_blockNumber element is about 65 bytes, while an eth_getLogs filter with many addresses can be several kilobytes. Measure bytes, not items.
- Does a higher plan raise the limit?
- No. It is an inspection limit on the gateway, the same on every plan. Plans change request rates, not body size.
- Does splitting a batch cost more?
- No. A batch of N requests already costs N requests against your RPS budget, so splitting changes when they are sent, not how many are counted.