- Symptom
- RPC returns
1010: Invalid Transaction: Custom error: <n>. The trailing integer is the actual cause —1010by itself only means the node refused the extrinsic. - Root cause
- Substrate-level wrapper around any rejected extrinsic. The inner
Custom errornumber is what you must decode — see the rest of this page for the common ones. - Fix
- Read the inner
Custom error: Ninteger and look it up. Don’t treat1010as the diagnosis. - Status
- Substrate framing, not a Midnight bug. Always present when any tx is rejected.
Midnight Error-Code Decoder
Plain-English mapping for the Midnight Network transaction error codes most often seen in the wild. Symptom, root cause, wallet-side fix, and upstream issue link per code.
UNKNOWN rather than guessed. This page is independent and not endorsed by the Midnight Foundation.
- Symptom
- Mainnet contract deploys reportedly fail with Substrate
1016: Immediately Dropped; the extrinsic never reaches a block. - Root cause
- UNKNOWN — not personally observed end-to-end. Open community thread on the Midnight dev forum reports 100% rejection on mainnet contract deploy with this code; no canonical fix has been published.
- Fix
- None known. Watch the Midnight dev forum thread and the
midnight-node1.0.0 release notes (TransactionExtension envelope migration is the leading suspect, but unverified). - Status
- Community-reported on mainnet contract deploys; no upstream issue link confirmed at time of writing. Listed here as
UNKNOWNdeliberately.
- Symptom
1010: Invalid Transaction: Custom error: 138on every send, even with NIGHT in the wallet.- Root cause
- Transaction had zero DUST inputs. DUST is mandatory for all Midnight fees, not NIGHT. The ledger’s balance check sums fee-paying coins and fails when DUST is missing.
- Fix
- YAMORI uses a
WalletFacadewith three sub-wallets (Unshielded + Shielded + Dust), registers NIGHT UTXOs for DUST generation first, and setsadditionalFeeOverhead: 300_000_000_000_000nwhen building fee inputs. Resolved in YAMORI v0.17 on 2026-04-08 with the first successful preprod tx00b12909…(3813 bytes, 100 NIGHT). - Status
- Fixed wallet-side. Soft drift noted: hardcoded
additionalFeeOverheadshould be replaced with a liveFeePricesquery when the SDK exposes one cleanly.
- Symptom
1010: Invalid Transaction: Custom error: 170intermittently after wallet load, often paired withUnable to download all specified imagesin the prover console.- Root cause
- S3 ZK proving-key download failed or returned partial data ⇒ prover used stale/missing keys ⇒ generated DUST spend proof that fails on-chain verification. Identified as
MalformedTransaction::InvalidDustSpendProofinmidnight-nodeledger/src/versions/common/types.rs. - Fix
- YAMORI ships a
MIDNIGHT_ERROR_CODESmap plus a_resolveErrorCode()helper that translates the Custom-error integer to a name in logs. On code 170 the wallet clears its_kmpCache(forces ZK key re-download from S3) and resets the facade. Applied to both transfer and shield/unshield paths. Resolved in v0.43 (2026-04-12); refined in v1.1.0 to avoid nuking the dust cache on every retry. - Status
- Fixed wallet-side. If it persists after a clean retry, check that the proof server version matches the active ledger and that
ZK_VERmatches what the network expects.
- Symptom
1010: Invalid Transaction: Custom error: 171after the wallet has been idle for a while.- Root cause
- Cached DUST coins moved outside their on-chain validity window while the wallet was offline. The ledger rejects spends of expired dust state.
- Fix
- YAMORI resets the facade with the dust-cache clear path on code 171 so the next tx rebuilds against a fresh DUST view. Resolved together with the 170 handler in v0.40 / v0.43.
- Status
- Fixed wallet-side.
- Symptom
- Combined
sendShielded+insertCoin-on-change transactions reportedly fail withEffectsCheckFailureas Custom error 186. - Root cause
- Sister case to issue #1206 — same family of effects-check failure, different trigger path. Tracked at midnightntwrk/midnight-node #1374 (opened 2026-04-21, P3 planned, OPEN as of 2026-05-02).
- Fix
- Nothing wallet-side. Wait on upstream node patch.
- Status
- Upstream tracked. No PR linked yet at time of writing.
- Symptom
- Every shielded mint / shield (
initSwap) on preprod returns1010: Invalid Transaction: Custom error: 199. Unshielded sends on the same wallet succeed. - Root cause
- Node-level
EffectsCheckFailure(AllCommitmentsSubsetCheckFailure)on shielded minting. Not a wallet bug — verified by upgrading the proof server from 6.1 to 8.1 with no change in behaviour. Tracked at midnightntwrk/midnight-node #1206 (opened 2026-04-01, OPEN as of 2026-05-02, no PR linked). - Fix
- Nothing wallet-side. YAMORI ships a friendly error-199 message in v0.48 explaining the upstream block.
initSwapis the correct shield method —transferTransactioncannot cross pools, so this is not a workable substitute. - Status
- Upstream tracked. Preprod shielded mint blocked. Watch testnet upgrades and node 1.0.0 RC release notes.
How to read a Midnight error
A Midnight tx failure surfaces as a layered chain. The outer frame is almost always Substrate’s 1010 Invalid Transaction. Inside that you get Custom error: N where N is the actual Midnight ledger code. JS callers see this through Effect’s cause chain, which preserves both layers but stringifies the inner one as a bare integer.
The pattern that has worked in practice: parse the Custom error: \d+ integer out of the message and look it up in a code map — YAMORI’s MIDNIGHT_ERROR_CODES map plus its _resolveErrorCode() helper turns the integer into a name in the wallet’s service-worker log so a developer never has to memorise codes. The full code table was reconstructed from ledger/src/versions/common/types.rs in midnightntwrk/midnight-node.
If your wallet treats 1010 itself as the error and stops there, you’ll never see the real diagnosis. Always extract and surface the inner integer before deciding what to do.