NightForge NightForge

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.

Truth rule. Every fix listed below is sourced from a YAMORI build session log or a real GitHub issue and cited inline. Codes that have not been personally observed end-to-end are flagged UNKNOWN rather than guessed. This page is independent and not endorsed by the Midnight Foundation.
Jump to 1010 1016 138 170 171 186 199
1010 Invalid Transaction Wrapper #1010
Symptom
RPC returns 1010: Invalid Transaction: Custom error: <n>. The trailing integer is the actual cause — 1010 by itself only means the node refused the extrinsic.
Root cause
Substrate-level wrapper around any rejected extrinsic. The inner Custom error number is what you must decode — see the rest of this page for the common ones.
Fix
Read the inner Custom error: N integer and look it up. Don’t treat 1010 as the diagnosis.
Status
Substrate framing, not a Midnight bug. Always present when any tx is rejected.
1016 Immediately Dropped Unknown #1016
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-node 1.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 UNKNOWN deliberately.
138 BalanceCheckOverspend Fixed in wallet #138
Symptom
1010: Invalid Transaction: Custom error: 138 on 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 WalletFacade with three sub-wallets (Unshielded + Shielded + Dust), registers NIGHT UTXOs for DUST generation first, and sets additionalFeeOverhead: 300_000_000_000_000n when building fee inputs. Resolved in YAMORI v0.17 on 2026-04-08 with the first successful preprod tx 00b12909… (3813 bytes, 100 NIGHT).
Status
Fixed wallet-side. Soft drift noted: hardcoded additionalFeeOverhead should be replaced with a live FeePrices query when the SDK exposes one cleanly.
170 InvalidDustSpendProof Fixed in wallet #170
Symptom
1010: Invalid Transaction: Custom error: 170 intermittently after wallet load, often paired with Unable to download all specified images in 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::InvalidDustSpendProof in midnight-node ledger/src/versions/common/types.rs.
Fix
YAMORI ships a MIDNIGHT_ERROR_CODES map 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_VER matches what the network expects.
171 OutOfDustValidityWindow Fixed in wallet #171
Symptom
1010: Invalid Transaction: Custom error: 171 after 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.
186 EffectsCheckFailure (sister to 199) Upstream tracked #186
Symptom
Combined sendShielded + insertCoin-on-change transactions reportedly fail with EffectsCheckFailure as 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.
199 InvariantViolation / AllCommitmentsSubsetCheckFailure Upstream tracked #199
Symptom
Every shielded mint / shield (initSwap) on preprod returns 1010: 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. initSwap is the correct shield method — transferTransaction cannot 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.