Sigil’s JSON-RPC server returns errors using the JSON-RPC 2.0 error object:
{
  "jsonrpc": "2.0",
  "error": {
    "code": -32602,
    "message": "invalid params",
    "data": { "field": "amount", "reason": "negative_value" }
  },
  "id": 1
}
Error messages are sanitised before leaving the node. Absolute filesystem paths and host:port substrings are redacted by node/sigil-rpc/src/middleware.rs::sanitize_error_message.

Standard JSON-RPC codes

These follow JSON-RPC 2.0:
CodeMeaningWhen
-32700Parse errorBody is not valid JSON.
-32600Invalid requestEnvelope shape is wrong.
-32601Method not foundMethod is not in this RPC profile’s method table.
-32602Invalid paramsparams failed type or range validation.
-32603Internal errorUnexpected failure inside the node.

Sigil-specific codes

CodeMeaningWhen
-32001InvalidSignatureSignature did not verify against the public key and envelope.
-32002NonceMismatchTransaction nonce is not the next expected for the DID.
-32003InsufficientFundsDID does not have the balance required for the transaction.
-32004Expiredexpires_at_height is at or below the current height.
-32005RateLimitedSource IP exceeded the rate limit.
-32006FeeTooLowFee is below the local fee market acceptance threshold.
-32007MempoolFullMempool is at capacity; retry with a higher fee.
-32008RevertedTransaction reverted during apply; data includes the revert reason.
-32009UnauthorisedThe signer lacks authority for this transaction.
-32010NotFoundRequested record does not exist.
-32011DisputedOperation blocked because the target is in dispute.
-32012GasExceededWasmtime gas budget exhausted.
-32013StateRootMismatchBlock header’s state root does not match the computed root.

Apply-time revert codes

When a transaction reverts during apply, error.code is -32008 and error.data.reason carries a domain-specific code. Examples:
DomainReasonMeaning
transferrecipient_not_foundRecipient DID is not registered.
dexinvariant_decreasedSwap would decrease the constant-product invariant.
dexslippage_exceededOutput below min_out or input above max_in.
nftroyalty_violationSale price violates the royalty policy.
namealready_registeredName has an active lease.
namereservedName is on the genesis reserved list.
mailkey_expiredRecipient encryption key has expired.
mailpolicy_deniedMailbox policy rejected the delivery.
mandatedelegation_too_deepMandate delegation chain exceeds the depth limit.
recoverytimelock_activeRecovery is in its timelock window; abort is still possible.
vigilsgas_tank_emptySubscription gas tank is empty.

Handling errors in clients

PatternRecommendation
RateLimitedHonour Retry-After; back off exponentially.
NonceMismatchRe-fetch the account nonce with sigil_getAccount; re-sign.
MempoolFullIncrease fee or wait one block.
RevertedInspect data.reason; do not retry without changing inputs.
ExpiredSet a longer expires_at_height; default is current height + 100.
InsufficientFundsRe-fetch balance with sigil_getBalance; refund or top up.
The full list of revert reasons lives in each executor’s error enum (node/sigil-core/src/executor_*.rs::*Error). Treat the reason string as stable; codes will not be renamed without a deprecation cycle.