Für Entwickler / JSON-RPC
Fehler und Grenzen
Fünf Fehlercodes tragen alles. -32005 ist der eine, den es lohnt, richtig zu behandeln, denn er bedeutet eine Grenze und keinen Fehler Ihrerseits - dieselbe Anfrage gelingt später.
Die fünf Codes
| Code | Value |
|---|---|
| -32602 | Invalid paramsa malformed address, block tag, filter id or topic filter |
| -32601 | Method not found or not availablean unregistered name, or one refused by design such as eth_sendTransaction |
| -32000 | Executiona revert, a decode failure, a signature failure, or a consensus rejection |
| -32005 | Limita rate limit, a full queue, a timeout, a size cap or a filter cap - every row on this page |
| -32603 | Internala write-ahead-log or coordinator failure; also every non-send error when you are on the WebSocket transport |
Der im Betrieb entscheidende Unterschied liegt zwischen -32000 und -32005. Ein Ausführungsfehler ist eine Tatsache über Ihre Transaktion, und ein erneuter Versuch ändert nichts; ein Grenzfehler ist eine Tatsache über die aktuelle Last des Node, und die identische Anfrage gelingt, sobald wieder Platz ist.
Kein error.data
Revert-Gründe können von Ihrer Bibliothek nicht dekodiert werden
A revert arrives as message text - "execution reverted: 0x<returndata>" - and error.data is absent.
Libraries decode custom errors and revert strings out of error.data, so on this chain they cannot. ethers and viem will both surface the raw message instead of a decoded error. If you need the reason, parse the hex out of the message yourself and decode it against your own ABI.
Die Seite zu den Abweichungen hat den Umweg.
Sending a transaction
| Grenze | Wert | Variable | Bei Überschreitung |
|---|---|---|---|
| Raw transaction sizechecked on the hex string BEFORE decoding, so an oversized transaction is a limit error rather than a decode error | 128 KiB | Konstante zur Übersetzungszeit | -32005 |
| Admission queuequeued transactions across all senders | 4,096 total | ADMISSION_CAPACITY | -32005 "sequencer admission queue is full" |
| Per sendercompile-time, so one sender cannot fill the queue with unfillable nonces | 64 | Konstante zur Übersetzungszeit | -32005 |
| Execution waitthe coordinator's own deadline is 5 s; the call waits until the transaction executes or this expires | 6 s | Konstante zur Übersetzungszeit | -32005 "transaction timed out waiting for execution" |
| Per execution batchMAX_ADMIT_PER_BATCH - a throughput mechanism, not a caller-visible limit | 512 | Konstante zur Übersetzungszeit | - |
Expensive reads
| Grenze | Wert | Variable | Bei Überschreitung |
|---|---|---|---|
| Token bucket burstguards eth_call, eth_estimateGas and eth_getLogs together | 256 | HEAVY_READ_BURST | -32005 "rate limit exceeded for expensive read methods" |
| Refill rateprocess-wide and shared by every caller - explicitly a backstop, not per-client limiting | 128/s | HEAVY_READ_PER_SEC | - |
| eth_getLogs spana span of 5,000 or more is refused outright | under 5,000 blocks | Konstante zur Übersetzungszeit | -32005 "log block range is too wide" |
| eth_getLogs matchesnarrow the filter or walk the range in windows | 10,000 | Konstante zur Übersetzungszeit | -32005 "eth_getLogs matched too many logs" |
The HTTP listener
| Grenze | Wert | Variable | Bei Überschreitung |
|---|---|---|---|
| Connections | 512 | RPC_MAX_CONNECTIONS | - |
| Request bodythe public vhost caps a request at 1 MiB before this applies, and 1 MiB of JSON-RPC batch is already thousands of calls | 2 MiB | RPC_MAX_REQUEST_BYTES | - |
| Response body | 16 MiB | RPC_MAX_RESPONSE_BYTES | - |
| Batch lengthsplit a larger batch client-side | 32 | RPC_MAX_BATCH | - |
| Keep-aliveTCP_NODELAY is on | 30 s | RPC_KEEP_ALIVE_SECS | - |
Filters
| Grenze | Wert | Variable | Bei Überschreitung |
|---|---|---|---|
| Filters per node | 1,024 | MAX_FILTERS | -32005 "filter limit reached" |
| Buffer per filterthe OLDEST entries are trimmed when you stop polling, so a slow poller loses the beginning of its backlog rather than the end | 1,024 entries | MAX_FILTER_BUFFER | - |
| Idle expirymeasured since the last poll, and expiry is silent - the next poll answers -32602 "filter not found" | 300 s | FILTER_TTL_SECS | -32602 |
Zwei Werte, die keine Konfiguration sind
MIN_GAS_PRICE (1 wei) und EXECUTION_SPEC (Cancun) sehen aus wie Einstellungen und sind bewusst Konstanten zur Übersetzungszeit.
Both are compile-time constants rather than environment variables, and that is a correctness requirement rather than an oversight. Either one made operator-tunable would let a replica reject or re-price a transaction the leader had accepted, and derivation would halt on the divergence. Pinning the hardfork also means a revm upgrade cannot silently change gas accounting underneath an already-settled chain.
Grenzen richtig behandeln
Es gibt weder eine Ratenbegrenzung pro Client noch einen Header mit dem verbleibenden Budget, ein Client kann sich also nicht anhand eines Signals selbst drosseln - er muss von Bauart aus wohlerzogen sein. Drei Dinge zählen:
- Bei
-32005zurückweichen, nicht sofort erneut versuchen. Der Eimer für schwere Lesezugriffe wird von allen Aufrufern geteilt, eine enge Wiederholungsschleife ist also der schnellste Weg, ihn für alle leer zu halten, Sie eingeschlossen. - Fenstern Sie Ihre
eth_getLogs-Bereiche unter 5.000 Blöcke und rechnen Sie mit der Treffer-Obergrenze bei 10.000. Auf einer Chain, die etwa zwei Minuten an Blöcken aufbewahrt, ist die praktische Grenze, auf die Sie zuerst stoßen, die Aufbewahrung und nicht die Spanne. - Halten Sie Batches bei 32. Darüber wird der Batch abgelehnt statt gekürzt.
// RPC_URL: https://rpc.picklechain.xyz on the public testnet, or a node of your own.
async function call(body, attempt = 0) {
const res = await fetch(RPC_URL, {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify(body),
});
const json = await res.json();
// -32005 is a limit, not a mistake: the same request works later.
if (json.error?.code === -32005 && attempt < 5) {
await new Promise((r) => setTimeout(r, 2 ** attempt * 250));
return call(body, attempt + 1);
}
return json;
}