JSON-RPC -32602 Invalid params is returned when a request envelope is well-formed but the params value is structurally or semantically unacceptable to the server. The JSON-RPC 2.0 specification requires params to be an array (positional) or an object (by-name), and the Ethereum JSON-RPC specification defines which methods use which form. Most real-world -32602 errors come from hex-quantity formatting mistakes, wrong parameter order, or sending a by-name object to a client that only implements positional params. This article shows how to validate arity, encoding, address case, and block tags before sending, how to bisect a failing call with curl, and how to document your endpoint's tolerance with a results table.
What -32602 Invalid params means in JSON-RPC 2.0
The JSON-RPC 2.0 specification defines a fixed set of error codes, and -32602 Invalid params is one of them. It is returned when the method exists and the request envelope is valid, but the params value is structurally or semantically unacceptable to the server. This is distinct from a method-not-found error, which indicates the method name itself is unknown.
The specification states that params MUST be an array (positional parameters) or an object (by-name parameters). Omitting params entirely is allowed only for methods that take no parameters. Sending params: {} to a method that expects positional arguments, or params: [..] to a method that expects a by-name object, is an immediate -32602 on a compliant server.
The Ethereum JSON-RPC specification builds on this by defining which methods use positional arrays and which accept by-name objects. Most execution-layer methods such as eth_getBalance, eth_call, and eth_getLogs use positional arrays. Some clients additionally accept by-name objects for certain methods, but this is not universal and varies by client and version.
- params MUST be an array or an object; omitting params is only valid for zero-argument methods.
- -32602 means the method was recognized but the arguments were rejected.
- The spec does not require the server to name the offending parameter in the error message.
- Provider-specific tolerance for by-name params is documented / varies by provider.
Positional versus by-name params and the client tolerance boundary
The Ethereum JSON-RPC specification uses positional arrays for nearly all standard methods. For example, eth_getBalance takes [address, blockTag]. A client that only implements positional params will return -32602 if you send {"address": "0x...", "blockTag": "latest"} as an object, even though the method exists and the values are correct.
Some clients, including certain versions of Geth and Erigon, accept by-name objects for a subset of methods as a convenience. This is not guaranteed by the specification and can change between versions. A request that passes on one endpoint can fail on another at any upgrade, which is why relying on by-name params in production code is risky.
The table below summarizes the boundary. Treat the 'by-name accepted' column as documented / varies by provider, not as a fixed guarantee.
- Positional arrays are the portable, spec-aligned form for Ethereum methods.
- By-name objects may work on some clients but are not universally supported.
- A client that only implements positional params returns -32602 for a by-name object.
- Always test against your specific endpoint and client version.
// Comparison of params forms for eth_getBalance
// Positional (portable):
{
"jsonrpc": "2.0",
"method": "eth_getBalance",
"params": ["0x742d35Cc6634C0532925a3b844Bc454e4438f44e", "latest"],
"id": 1
}
// By-name (may return -32602 on some clients):
{
"jsonrpc": "2.0",
"method": "eth_getBalance",
"params": {"address": "0x742d35Cc6634C0532925a3b844Bc454e4438f44e", "blockTag": "latest"},
"id": 1
}Hex quantity and data encoding as the most common real-world cause
The Ethereum JSON-RPC specification distinguishes between QUANTITY and DATA encodings. QUANTITY values must be 0x-prefixed, use the fewest possible hex digits, and have no leading zeros. DATA values must be 0x-prefixed and even-length. A decimal 1000 where the spec requires 0x3e8 is a frequent cause of -32602, as is a quantity like 0x03e8 with a leading zero.
String concatenation is the usual culprit. Building a hex string with '0x' + number.toString(16) works for simple cases but breaks when the number is zero (produces '0x0', which is valid) or when leading zeros are introduced by padding logic. Use a dedicated encoder such as ethers.js hexlify or viem's toHex to avoid these mistakes.
Address case also matters. The specification accepts lowercase and checksummed addresses, but some clients reject all-uppercase or mixed-case addresses that do not match the EIP-55 checksum. Normalizing addresses with getAddress from ethers.js or getAddress from viem prevents this class of -32602.
- QUANTITY: 0x-prefixed, no leading zeros, minimal hex digits.
- DATA: 0x-prefixed, even-length hex.
- Use hexlify / toHex instead of manual string concatenation.
- Normalize addresses to lowercase or valid EIP-55 checksum before sending.
// Correct encoding with ethers.js v6
import { hexlify, getAddress } from 'ethers';
const blockNumber = 1000;
const quantity = hexlify(blockNumber); // '0x3e8'
const address = getAddress('0x742d35cc6634c0532925a3b844bc454e4438f44e');
// Incorrect: decimal where hex is required
// const badQuantity = 1000; // -32602
// Incorrect: leading zero in quantity
// const badQuantity2 = '0x03e8'; // -32602 on strict clientsA pre-flight validation function for Node.js clients
Validating arguments before the request leaves your process is the most effective way to avoid -32602. The function below checks arity, hex-quantity formatting, address case, and block-tag validity for a small set of common methods. Extend the schema map as you add methods.
The validator returns an array of error strings. If the array is empty, the request is safe to send. This is not a substitute for server-side validation, but it catches the majority of client-side mistakes before they consume a round trip.
- Check arity against the method's expected parameter count.
- Validate QUANTITY fields with a regex that rejects leading zeros.
- Validate addresses with a regex and optionally EIP-55 checksum.
- Validate block tags against the allowed set or a hex block number.
// validateParams.js — drop-in pre-flight validator
const QUANTITY_RE = /^0x([1-9a-f][0-9a-f]*|0)$/;
const ADDRESS_RE = /^0x[0-9a-fA-F]{40}$/;
const BLOCK_TAGS = new Set(['latest', 'safe', 'finalized', 'earliest', 'pending']);
const SCHEMAS = {
eth_getBalance: { arity: 2, types: ['address', 'blockTag'] },
eth_getTransactionCount: { arity: 2, types: ['address', 'blockTag'] },
eth_call: { arity: 2, types: ['object', 'blockTag'] },
eth_getLogs: { arity: 1, types: ['object'] },
eth_blockNumber: { arity: 0, types: [] },
};
function validateParams(method, params) {
const errors = [];
const schema = SCHEMAS[method];
if (!schema) return [`Unknown method: ${method}`];
if (!Array.isArray(params)) {
errors.push('params must be an array for this method');
return errors;
}
if (params.length !== schema.arity) {
errors.push(`Expected ${schema.arity} params, got ${params.length}`);
}
schema.types.forEach((type, i) => {
const v = params[i];
if (type === 'address' && !ADDRESS_RE.test(v)) errors.push(`param[${i}] invalid address`);
if (type === 'blockTag') {
const ok = BLOCK_TAGS.has(v) || QUANTITY_RE.test(v) || /^0x[0-9a-fA-F]{64}$/.test(v);
if (!ok) errors.push(`param[${i}] invalid block tag`);
}
if (type === 'object' && (typeof v !== 'object' || v === null)) errors.push(`param[${i}] must be an object`);
});
return errors;
}
// Usage
const errs = validateParams('eth_getBalance', ['0x742d35Cc6634C0532925a3b844Bc454e4438f44e', 'latest']);
if (errs.length) console.error('Pre-flight failed:', errs);
else console.log('Request is safe to send');Distinguishing -32602 from neighbouring error codes
Fast triage depends on knowing which layer failed. -32600 Invalid Request means the envelope itself is malformed: wrong jsonrpc version, missing method, or an id of an invalid type. -32602 means the envelope is fine but the arguments are wrong. -32603 Internal error means the server encountered a fault while processing a valid request.
The -32000-range codes are reserved for implementation-defined server errors. In Ethereum clients these often represent chain-specific conditions such as an out-of-range block, a filter not found, or a transaction rejected by the pool. For example, an eth_getLogs call with a block range exceeding the node's limit may return a -32000-range error rather than -32602, because the arguments are structurally valid but the requested range is not serviceable. See eth_getLogs block-range limits and large scans for that specific case.
If you are unsure whether a failure is -32602 or -32603, replay the exact call with curl and inspect the error object. The code field is authoritative; the message field is not standardized and may be empty or misleading.
- -32600: malformed envelope (bad jsonrpc version, bad id type).
- -32602: well-formed request, unacceptable arguments.
- -32603: server-side fault while processing a valid request.
- -32000 range: node/chain-specific conditions such as out-of-range block.
Bisecting a -32602 with curl and incremental replay
When a call fails with -32602, the fastest path to the offending argument is to replay the exact request with curl, then strip optional params and re-add them one at a time. Start with the full request to confirm the error, then remove the last parameter and retry. If the error disappears, the removed parameter is the culprit.
For methods with optional parameters, such as eth_getLogs with fromBlock and toBlock, test each combination. Some clients reject null where a value is required, and others accept null as a default. Document which behavior your endpoint exhibits.
The curl example below sends a minimal eth_getBalance request. Replace the URL with your RPC endpoint and adjust the params to reproduce your failure.
- Replay the exact failing call with curl to confirm the error code.
- Strip optional params, then re-add one at a time.
- Test null versus omitted for optional fields.
- Record the exact params form that triggers -32602.
curl -X POST https://your-endpoint.example \
-H 'Content-Type: application/json' \
-d '{
"jsonrpc": "2.0",
"method": "eth_getBalance",
"params": ["0x742d35Cc6634C0532925a3b844Bc454e4438f44e", "latest"],
"id": 1
}'Documenting your endpoint's tolerance with a results table
Because validation rules vary by client and version, the only reliable way to know what your endpoint accepts is to measure it. Build a small matrix of methods, params forms, and expected outcomes, then run it against each endpoint you depend on. Fill in the table below with your own results.
Run each row as a separate request and record the HTTP status, the JSON-RPC error code, and the message. This gives you a regression baseline you can re-run after client upgrades. The table is intentionally empty; the values are for you to measure, not for us to assert.
- Method: the JSON-RPC method name.
- Client: the node software and version behind the endpoint.
- Params form: positional array or by-name object.
- Accepted?: yes or no.
- Code: the JSON-RPC error code returned, if any.
- Message: the error message text, if any.
| Method | Client | Params form | Accepted? | Code | Message |
|--------|--------|-------------|-----------|------|---------|
| eth_getBalance | Geth v1.x | positional | | | |
| eth_getBalance | Geth v1.x | by-name | | | |
| eth_getBalance | Erigon v2.x | positional | | | |
| eth_getBalance | Erigon v2.x | by-name | | | |
| eth_call | Geth v1.x | positional | | | |
| eth_getLogs | Geth v1.x | positional | | | |Troubleshooting checklist for -32602
Work through the following checklist in order. Most -32602 errors are caused by one of these issues, and the checklist is ordered by frequency of occurrence in practice.
If none of these resolve the error, the issue may be client-specific tolerance. Compare your request against the Ethereum JSON-RPC specification and the JSON-RPC 2.0 specification to confirm the expected params form.
- Wrong parameter order: positional arrays are order-sensitive.
- Quantity versus data encoding: 0x3e8 is a quantity; 0x03e8 is invalid.
- null where a value is required: some clients reject null for required fields.
- Address without 0x prefix: always include the prefix.
- Block tag the node does not support: safe and finalized may not be available on all chains.
- By-name object sent to a positional-only client.
- Leading zeros in a hex quantity.
- Missing required parameter entirely.
Limitations and tradeoffs of client-side validation
The JSON-RPC 2.0 specification does not require an informative error message. A server may return -32602 with no indication of which parameter failed, which means client-side validation is the only way to get a precise diagnosis. This is a limitation of the protocol, not of any specific provider.
Validation rules also vary by client version. A request that passes on one endpoint can fail on another at any upgrade, and a by-name object that works today may be rejected after a node upgrade. Maintaining a schema map for every method you call is ongoing work, but it is cheaper than debugging production failures.
Finally, client-side validation cannot catch semantic errors that only the server can evaluate, such as a block number that is valid hex but beyond the chain head. Those cases return -32000-range errors, not -32602, and require different handling. For state-dependent calls, see eth_call state overrides and simulation.
- The spec does not require the server to name the offending parameter.
- Validation rules vary by client version and can change at any upgrade.
- Client-side validation cannot catch server-side semantic errors.
- Maintaining a schema map is ongoing work but reduces production failures.
Next steps for robust RPC argument handling
Start by adding the pre-flight validator to your client and running it against your most-used methods. Then build the results table for each endpoint you depend on, and re-run it after client upgrades. This gives you a regression baseline and a clear picture of your endpoint's tolerance.
For related topics, see Nonce management with eth_getTransactionCount for transaction-count argument handling, and eth_getLogs event and topic filtering for filter argument validation. If you are choosing an endpoint, the RPC endpoints guide covers endpoint selection criteria.
To explore supported networks and endpoints, visit the Ethereum network page, the OnFinality Learn hub, or review RPC pricing and the API service for integration options.
- Add the pre-flight validator to your client.
- Build and re-run the results table after upgrades.
- Review related argument-handling guides for other methods.
- Choose endpoints that match your params form requirements.