Use this reference to diagnose and handle Relayer errors. Three categories exist: WebSocket control errors (subscribe/unsubscribe), transaction relay errors (gasless V3), and transaction broadcast errors.
The Relayer returns errors as JSON messages. Control action errors use "fail" status. Transaction action errors include a failed array with per-transaction details.
Control action error (subscribe / unsubscribe)
{
"action": "subscribe",
"status": "fail",
"reason": "topic limit reached"
}
Transaction action error (relay / broadcast)
{
"action": "relay",
"status": "failed",
"requestId": "relay-001",
"hashes": [],
"failed": [
{ "index": 0, "reason": "missing relayer" }
]
}
WebSocket-level errors
The Relayer returns these errors in response to subscribe, unsubscribe, or malformed control messages.
| Error | Description | Resolution |
|---|
topic limit reached | The connection already has 64 active topic subscriptions | Unsubscribe from unused topics before subscribing to new ones |
rate limit exceeded | You sent more than 64 control messages within a 5-second window | Implement client-side rate limiting. Batch subscriptions at connection open. |
invalid bech32 address in topic | The address in an address/{bech32} topic failed bech32 decode or is not a valid erd1... address | Validate addresses before subscribing |
unknown topic | The topic string does not match any supported pattern | Check the supported topics list |
message too large | A single WebSocket frame exceeded 4 MB | Split large batch payloads into smaller messages |
unknown action | The action field does not match a supported action (subscribe, unsubscribe, relay, broadcast) | Use a supported action string |
A rate limit exceeded error closes the connection. Reconnect with exponential backoff and reduce your control message frequency.
Transaction relay errors
These errors appear in failed[].reason of a relay response. Each corresponds to a specific validation failure in the co-signing pipeline.
| Error | Description | Resolution |
|---|
missing relayer | The transaction object lacks a relayer field | Add the relayer field set to the shard-specific relayer address before the user signs |
shard mismatch: sender_shard=X, relayer_shard=Y | The sender’s shard and the provided relayer address shard differ | Use shard derivation to select the correct relayer address. See shard routing. |
unconfigured relayer | The relayer field contains an address not recognized as a deployed shard relayer key | Use only the addresses listed in the shard routing table |
signing capacity exceeded, try again later | The Relayer’s signing queue is full | Back off and retry with exponential backoff starting at 500 ms |
aggregator shutdown | The internal transaction aggregator is shutting down | Reconnect after a brief delay; the Relayer is restarting |
Transaction broadcast errors
These errors appear in failed[].reason of a broadcast response. The network or the Relayer’s pre-validation returns them when rejecting a transaction.
| Error | Description | Resolution |
|---|
invalid signature | The signature does not match the canonical serialization of the transaction | Verify the signing serialization matches the MultiversX specification. Confirm all required fields are present before signing. |
invalid nonce | The nonce is already consumed or too far ahead of the current account nonce | Fetch the current nonce from the API before constructing the transaction |
insufficient balance | The sender account lacks enough EGLD to cover value + gasPrice * gasLimit | Check account balance before sending |
invalid receiver | The receiver field is not a valid bech32 address | Validate the receiver address client-side before submitting |
gas limit too low | gasLimit is below the minimum required for the transaction type | Use gas estimation from the MultiversX SDK or increase gasLimit |
invalid chain id | The chainID does not match the target network (for example, "T" submitted to mainnet) | Set chainID to "1" for mainnet |
Subscription response codes
These appear in the status field of acknowledgments for subscribe and unsubscribe actions.
| Status | Meaning |
|---|
ok | The action succeeded |
fail | The action failed. Check the reason field for details. |
Handling errors in code
ws.onmessage = (event) => {
const msg = JSON.parse(event.data);
// Control action error
if (msg.status === "fail") {
console.error(`Action "${msg.action}" failed: ${msg.reason}`);
if (msg.reason === "rate limit exceeded") {
// Stop sending control messages for the remainder of the 5-second window
scheduleRetry(5000);
}
if (msg.reason === "topic limit reached") {
// Prune stale subscriptions before adding new ones
pruneSubscriptions();
}
return;
}
// Transaction action errors
if ((msg.action === "relay" || msg.action === "broadcast") && msg.failed?.length > 0) {
for (const failure of msg.failed) {
console.error(`TX[${failure.index}] failed: ${failure.reason}`);
if (failure.reason === "signing capacity exceeded, try again later") {
retryWithBackoff(failure.index);
}
if (failure.reason?.startsWith("shard mismatch")) {
console.error("Shard mismatch: check relayer address selection logic");
}
}
}
};
Operational checks
- Check
status and failed in every response. Assume nothing succeeded until confirmed.
- Correlate with
requestId. Include a unique requestId in every relay and broadcast action so you can match responses to requests.
- Validate before sending. Check bech32 addresses, nonces, and shard assignment client-side to avoid round-trip errors.
- Implement exponential backoff. For
signing capacity exceeded and rate limit errors, start at 500 ms and cap at 30 seconds.
- Log error reasons. The
reason strings are stable and machine-parseable. Use them for automated error handling.