nautechsystems/nautilus_trader · error
Receipt verification is locally invalid for transaction {tx_
Error message
Receipt verification is locally invalid for transaction {tx_hash} What it means
During receipt-based finality polling, the verification layer returned VerificationOutcome::LocallyInvalid for the transaction, meaning the fetched receipt contradicts locally-held expectations (e.g. receipt fields disagree with the signed transaction or local record). The client bails out rather than treating the tx as confirmed.
Source
Thrown at crates/adapters/blockchain/src/execution/client.rs:3367
}
}
VerificationOutcome::Retryable(_) => {
continue;
}
VerificationOutcome::Disagreement(_) => {
return Ok(InclusionOutcome::Pending(format!(
"Receipt verification disagreed for transaction {tx_hash}; the intent stays occupied for reconciliation"
)));
}
VerificationOutcome::Unavailable(_) => {
log::warn!(
"Finality poll {}/{} for transaction {tx_hash} was unavailable",
attempt + 1,
self.receipt_max_polls
);
}
VerificationOutcome::LocallyInvalid(_) => {
anyhow::bail!(
"Receipt verification is locally invalid for transaction {tx_hash}"
);
}
}
}
self.database
.record_execution_status(
prepared.intent_id,
&tx_hash.to_string(),
TransactionStatus::Dropped,
None,
None,
None,
None,
None,
)
.await?;View on GitHub (pinned to 18893faf8b)
Solutions
- Verify the RPC endpoint and chain ID match the intended network
- Re-fetch the receipt manually and compare block number, status, and hash against the signed transaction
- Switch to a trusted/redundant RPC provider
- Re-check whether the tx was replaced (e.g. by a same-nonce resubmission) and restart finality tracking for the new tx
Example fix
// before: single flaky endpoint let client = ExecutionClient::new(rpc_url); // after: validated endpoint with matching chain id assert_eq!(client.chain_id().await?, expected_chain_id); let client = ExecutionClient::new(verified_rpc_url);
Defensive patterns
Strategy: retry
Validate before calling
let receipt = rpc.get_receipt(tx_hash).await?; assert_eq!(receipt.transaction_hash, tx_hash, "receipt does not match requested tx hash");
Try / catch
match res {
Err(e) if e.to_string().contains("locally invalid") => {
switch_to_backup_rpc();
reverify_receipt(tx_hash)?;
}
other => other?,
} Prevention
- Pin RPC endpoints to the correct chain ID and verify at startup
- Use redundant providers with receipt cross-checking
- Track replaced transactions (same nonce) and restart finality tracking
- Compare receipt fields against the signed tx before trusting them
When it happens
Trigger: Polling a transaction receipt to finality when the returned receipt fails local validation — wrong status, mismatched block/hash versus the signed tx, or a receipt from a different transaction than tx_hash under an unreliable provider.
Common situations: Misbehaving or misconfigured RPC endpoint returning inconsistent receipts; tx was replayed/replaced (same hash on a forked chain); querying the wrong network/chain ID so the hash resolves to an unrelated receipt.
Understand the failure class
Background: Checksum mismatch errors: "checksum verification failed", "digest mismatch", "expected vs actual checksum" — what they mean and how to fix them — this error's family across 41 libraries.
Related errors
- Included wrap transaction {tx_hash} has invalid block number
- {context} verification disagreed
- {context} verification is locally invalid
- Canonical nonce advanced without an authenticated signer tra
- Finalized header verification disagreed
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/26b5390359f51fa4.
Report an issue: GitHub.