<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: cobra</title>
    <description>The latest articles on DEV Community by cobra (@cobra1).</description>
    <link>https://dev.to/cobra1</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3881249%2F8aa098dd-516a-425f-a0b4-070e524f88eb.png</url>
      <title>DEV Community: cobra</title>
      <link>https://dev.to/cobra1</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/cobra1"/>
    <language>en</language>
    <item>
      <title>When proofs fail on Midnight: Debugging proof server errors and ZK generation failures</title>
      <dc:creator>cobra</dc:creator>
      <pubDate>Mon, 15 Jun 2026 14:24:59 +0000</pubDate>
      <link>https://dev.to/cobra1/when-proofs-fail-on-midnight-debugging-proof-server-errors-and-zk-generation-failures-42b</link>
      <guid>https://dev.to/cobra1/when-proofs-fail-on-midnight-debugging-proof-server-errors-and-zk-generation-failures-42b</guid>
      <description>&lt;p&gt;This guide shows how to diagnose and fix four common proof-generation failures on Midnight: a proof server that is not responding, a slow first proof or client timeout, proof rejection caused by a wire format mismatch, and version mismatches between the proof server and the ledger stack. Each command and log example in this guide was tested in a local environment.&lt;/p&gt;

&lt;p&gt;Use this guide when your Midnight DApp cannot reach the proof server, proof generation times out, &lt;code&gt;/check&lt;/code&gt; or &lt;code&gt;/prove&lt;/code&gt; rejects a request, or proof generation starts failing after a version change.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this guide covers
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Proof server liveness and version verification&lt;/li&gt;
&lt;li&gt;Proof server not responding&lt;/li&gt;
&lt;li&gt;Slow first proof or timeout&lt;/li&gt;
&lt;li&gt;Wire format mismatch on proof server requests&lt;/li&gt;
&lt;li&gt;Version mismatch between the proof server and the local ledger stack&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Tested environment
&lt;/h2&gt;

&lt;p&gt;Note: The examples below use focused local reproductions rather than a single DApp flow. The timeout reproduction uses a local helper script, &lt;code&gt;k16-direct-prove-timeout.mjs&lt;/code&gt;, with the compiled &lt;code&gt;transferOwnership&lt;/code&gt; circuit from OpenZeppelin’s test-only &lt;a href="https://github.com/OpenZeppelin/compact-contracts/blob/736e28960486973a2110adbf45541aaf44f7388c/contracts/src/access/test/mocks/MockZOwnablePK.compact" rel="noopener noreferrer"&gt;&lt;code&gt;MockZOwnablePK.compact&lt;/code&gt;&lt;/a&gt;. The helper generates a valid serialized preimage before calling &lt;code&gt;/prove&lt;/code&gt;. The script and compiled artifacts are not included with this article, so the commands show the exact tested invocation but are not copy-paste-ready on their own. The version-mismatch section uses a local Hello World DApp flow. The wire-format section uses saved &lt;code&gt;/check&lt;/code&gt; payloads so request encoding can be tested in isolation. Use the same diagnostic pattern in your own Midnight DApp.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Item&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Verified as of&lt;/td&gt;
&lt;td&gt;April 16, 2026&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;OS&lt;/td&gt;
&lt;td&gt;macOS 15.6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CPU&lt;/td&gt;
&lt;td&gt;arm64&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Docker&lt;/td&gt;
&lt;td&gt;29.1.2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Node.js&lt;/td&gt;
&lt;td&gt;22.21.1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;npm&lt;/td&gt;
&lt;td&gt;10.9.4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Compact&lt;/td&gt;
&lt;td&gt;0.5.1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Compact compile&lt;/td&gt;
&lt;td&gt;0.30.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Proof server image&lt;/td&gt;
&lt;td&gt;&lt;code&gt;midnightntwrk/proof-server:8.0.3&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;Before you start, make sure you have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Docker Desktop running&lt;/li&gt;
&lt;li&gt;Node.js installed&lt;/li&gt;
&lt;li&gt;Compact installed&lt;/li&gt;
&lt;li&gt;A local Midnight project or DApp flow that triggers proof generation&lt;/li&gt;
&lt;li&gt;Terminal access&lt;/li&gt;
&lt;li&gt;The proof server image version that matches your local stack&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Start from a healthy proof server
&lt;/h2&gt;

&lt;p&gt;Start with one known-good proof server. Do this before changing versions, editing payloads, or tuning timeouts.&lt;/p&gt;

&lt;p&gt;Run the standalone proof server on port &lt;code&gt;6300&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;--name&lt;/span&gt; midnight-proof-server-319-k16-cold &lt;span class="nt"&gt;-p&lt;/span&gt; 6300:6300 midnightntwrk/proof-server:8.0.3 &lt;span class="nt"&gt;--&lt;/span&gt; midnight-proof-server &lt;span class="nt"&gt;-v&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In another terminal, use &lt;code&gt;/version&lt;/code&gt; as the proof server liveness and version check. The proof server does not expose a dedicated &lt;code&gt;/health&lt;/code&gt; route, so a successful &lt;code&gt;/version&lt;/code&gt; response confirms that the service is reachable and reports the running version:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-i&lt;/span&gt; http://localhost:6300/version
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A healthy proof server returns &lt;code&gt;HTTP/1.1 200 OK&lt;/code&gt; and the version string:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;HTTP/1.1 200 OK
content-type: text/plain; charset=utf-8

8.0.3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also inspect the container and recent logs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker ps &lt;span class="nt"&gt;--filter&lt;/span&gt; &lt;span class="s2"&gt;"name=midnight-proof-server"&lt;/span&gt;
docker logs &lt;span class="nt"&gt;--tail&lt;/span&gt; 20 midnight-proof-server-319-k16-cold
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A healthy startup eventually shows the server listening on &lt;code&gt;0.0.0.0:6300&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;starting service: "actix-web-service-0.0.0.0:6300", workers: 10, listening on: 0.0.0.0:6300
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Fix a proof server that is not responding
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Symptom
&lt;/h3&gt;

&lt;p&gt;The standalone proof server on the default local endpoint is not responding. Start by checking the proof server container state, preserved logs, and the &lt;code&gt;/version&lt;/code&gt; liveness check on port &lt;code&gt;6300&lt;/code&gt;. For this test, the endpoint was &lt;code&gt;http://localhost:6300/version&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  What to check
&lt;/h3&gt;

&lt;p&gt;Check four things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Is the proof server container running?&lt;/li&gt;
&lt;li&gt;Do the startup logs show a healthy startup state?&lt;/li&gt;
&lt;li&gt;Does &lt;code&gt;http://localhost:6300/version&lt;/code&gt; respond?&lt;/li&gt;
&lt;li&gt;After stopping the container, does Docker show that the container exited while &lt;code&gt;/version&lt;/code&gt; stops responding?&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Commands
&lt;/h3&gt;

&lt;p&gt;For this test, I used a named standalone container without &lt;code&gt;--rm&lt;/code&gt; so Docker state and logs would still be available after the container was stopped.&lt;/p&gt;

&lt;p&gt;Start the proof server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;--name&lt;/span&gt; midnight-proof-server-319-a &lt;span class="nt"&gt;-p&lt;/span&gt; 6300:6300 midnightntwrk/proof-server:8.0.3 &lt;span class="nt"&gt;--&lt;/span&gt; midnight-proof-server &lt;span class="nt"&gt;-v&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then verify the healthy state:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker ps &lt;span class="nt"&gt;--filter&lt;/span&gt; &lt;span class="s2"&gt;"name=midnight-proof-server-319-a"&lt;/span&gt;
docker logs midnight-proof-server-319-a
curl &lt;span class="nt"&gt;-i&lt;/span&gt; http://localhost:6300/version
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this test, &lt;code&gt;docker ps&lt;/code&gt; showed the container running on &lt;code&gt;0.0.0.0:6300-&amp;gt;6300/tcp&lt;/code&gt;, the startup logs included &lt;code&gt;Actix runtime found; starting in Actix runtime&lt;/code&gt; and &lt;code&gt;listening on: 0.0.0.0:6300&lt;/code&gt;, and the &lt;code&gt;/version&lt;/code&gt; check returned &lt;code&gt;HTTP/1.1 200 OK&lt;/code&gt; with body &lt;code&gt;8.0.3&lt;/code&gt;. That established a known-good baseline before reproducing the failure.&lt;/p&gt;

&lt;p&gt;Now stop that same standalone container and diagnose the result with Docker-based checks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker stop midnight-proof-server-319-a
docker ps &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="nt"&gt;--filter&lt;/span&gt; &lt;span class="s2"&gt;"name=midnight-proof-server-319-a"&lt;/span&gt;
docker inspect midnight-proof-server-319-a
docker logs midnight-proof-server-319-a
curl &lt;span class="nt"&gt;-i&lt;/span&gt; http://localhost:6300/version
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  What the logs show
&lt;/h3&gt;

&lt;p&gt;This test produced a real non-responding state, and the strongest evidence came from Docker rather than from &lt;code&gt;curl&lt;/code&gt; alone:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;docker ps -a&lt;/code&gt; showed the container had exited.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;docker inspect&lt;/code&gt; showed &lt;code&gt;"Status": "exited"&lt;/code&gt; and &lt;code&gt;"Running": false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;docker logs&lt;/code&gt; were still preserved because the container had been created without &lt;code&gt;--rm&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;/version&lt;/code&gt; endpoint no longer responded on &lt;code&gt;http://localhost:6300/version&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The preserved logs are also useful because they show what happened at shutdown. They do not show a crash or an application exception. Instead, they show a clean stop sequence beginning with &lt;code&gt;SIGTERM received; starting graceful shutdown&lt;/code&gt;, followed by worker shutdown lines and &lt;code&gt;accept thread stopped&lt;/code&gt;. After that, &lt;code&gt;curl -i http://localhost:6300/version&lt;/code&gt; failed with &lt;code&gt;curl: (7) Failed to connect to localhost port 6300&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Root cause
&lt;/h3&gt;

&lt;p&gt;The most conservative, evidence-backed root cause is that the standalone container process had stopped, so nothing was listening on port &lt;code&gt;6300&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fix
&lt;/h3&gt;

&lt;p&gt;Because this test used a named container without &lt;code&gt;--rm&lt;/code&gt;, the exact tested recovery command was:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker start midnight-proof-server-319-a
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Verify the fix
&lt;/h3&gt;

&lt;p&gt;After restarting the same container, verify &lt;code&gt;/version&lt;/code&gt; again:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-i&lt;/span&gt; http://localhost:6300/version
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this test, that final check returned &lt;code&gt;HTTP/1.1 200 OK&lt;/code&gt; with body &lt;code&gt;8.0.3&lt;/code&gt;, confirming that the proof server was reachable again on the standard local endpoint.&lt;/p&gt;

&lt;h2&gt;
  
  
  Diagnose a slow first proof or timeout
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Symptom
&lt;/h3&gt;

&lt;p&gt;The first proof request is slow or fails with an abort-style timeout. On a cold proof server, the server may need to download or initialize ZK parameter and key material before the proof can finish. In this test, the logs showed cold parameter and key downloads, a real &lt;code&gt;/prove&lt;/code&gt; timeout, and success after increasing the timeout.&lt;/p&gt;

&lt;h3&gt;
  
  
  What to check
&lt;/h3&gt;

&lt;p&gt;Check three things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Did the proof flow reach &lt;code&gt;/prove&lt;/code&gt;?&lt;/li&gt;
&lt;li&gt;Did the proof server start cold and fetch missing parameter or key material?&lt;/li&gt;
&lt;li&gt;Does the same proof succeed with a higher timeout?&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Commands
&lt;/h3&gt;

&lt;p&gt;The commands below are the exact commands used in the tested reproduction. They depend on the local helper script and compiled circuit assets described above, so treat them as illustrative unless you have equivalent local assets.&lt;/p&gt;

&lt;p&gt;Start from a cold proof server and watch its logs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker logs &lt;span class="nt"&gt;--tail&lt;/span&gt; 80 midnight-proof-server-319-k16-cold
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run the direct proof path with a low timeout:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;K16_PROVE_TIMEOUT_MS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1000 node k16-direct-prove-timeout.mjs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then run the same direct proof path with a higher timeout:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;K16_PROVE_TIMEOUT_MS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;300000 node k16-direct-prove-timeout.mjs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  What the logs show
&lt;/h3&gt;

&lt;p&gt;The cold proof server fetched missing public parameters and key material:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Ensuring zswap key material is available...
Missing public parameters for k=10. Attempting to download from the host ...
Missing public parameters for k=11. Attempting to download from the host ...
Missing public parameters for k=12. Attempting to download from the host ...
Missing zero-knowledge proving key for Zswap inputs. Attempting to download from the host ...
Missing zero-knowledge proving key for Dust spends. Attempting to download from the host ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The low-timeout proof attempt reached the proof path and then aborted:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PREIMAGE_OK
serializedPreimage.length=323
publicTranscript.length=36
privateTranscriptOutputs.length=2
PROVE_ATTEMPT_START
proofServer=http://localhost:6300
circuitId=transferOwnership
timeoutMs=1000
PROVE_ERROR
error.name=AbortError
error.message=The user aborted a request.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The proof server also showed the &lt;code&gt;/prove&lt;/code&gt; request:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;POST /prove HTTP/1.1; took 5.111326s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The higher-timeout run succeeded:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PROVE_ATTEMPT_START
proofServer=http://localhost:6300
circuitId=transferOwnership
timeoutMs=300000
PROVE_OK
proof.length=4508
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Root cause
&lt;/h3&gt;

&lt;p&gt;The client timeout was too low for the first proof path. The proof server was alive, but the client aborted before proof generation finished.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fix
&lt;/h3&gt;

&lt;p&gt;Increase the proof provider timeout for first-run proof generation. Keep the timeout high enough for cold parameter and key initialization.&lt;/p&gt;

&lt;h3&gt;
  
  
  Verify the fix
&lt;/h3&gt;

&lt;p&gt;Run the same proof path again with the higher timeout:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;K16_PROVE_TIMEOUT_MS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;300000 node k16-direct-prove-timeout.mjs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The proof succeeds when the timeout is high enough:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PROVE_OK
proof.length=4508
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Do not treat every timeout as a DUST or wallet problem. In this test, the valid timeout evidence used a direct &lt;code&gt;/prove&lt;/code&gt; path and avoided an earlier wallet/deploy path that failed before proof generation with insufficient DUST.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fix proof rejection caused by a wire format mismatch
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Symptom
&lt;/h3&gt;

&lt;p&gt;The proof server rejects a request even though the server is running. This can happen when the request body does not match the serialized wire format expected by &lt;code&gt;/check&lt;/code&gt; or &lt;code&gt;/prove&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  What to check
&lt;/h3&gt;

&lt;p&gt;Check whether your client sends the exact serialized payload expected by the proof server. Do not hand-edit, truncate, stringify, or re-encode the binary request body.&lt;/p&gt;

&lt;p&gt;The examples below use &lt;code&gt;./evidence&lt;/code&gt; as the evidence folder. Replace it with your own folder if you store test files somewhere else.&lt;/p&gt;

&lt;h3&gt;
  
  
  Commands
&lt;/h3&gt;

&lt;p&gt;Send a known-good &lt;code&gt;/check&lt;/code&gt; payload:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-sS&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-D&lt;/span&gt; ./evidence/05-good-check.headers.txt &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-o&lt;/span&gt; ./evidence/05-good-check.body.bin &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'Content-Type: application/octet-stream'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--data-binary&lt;/span&gt; @./evidence/05-wire-format-good-check.bin &lt;span class="se"&gt;\&lt;/span&gt;
  http://127.0.0.1:6300/check
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then send a truncated copy of that payload:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-sS&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-D&lt;/span&gt; ./evidence/05-bad-check.headers.txt &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-o&lt;/span&gt; ./evidence/05-bad-check.body.bin &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'Content-Type: application/octet-stream'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--data-binary&lt;/span&gt; @./evidence/05-wire-format-bad-check-truncated.bin &lt;span class="se"&gt;\&lt;/span&gt;
  http://127.0.0.1:6300/check
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  What the logs show
&lt;/h3&gt;

&lt;p&gt;The good payload returned &lt;code&gt;200 OK&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GOOD_HEADERS
HTTP/1.1 200 OK
content-length: 30
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The truncated payload returned &lt;code&gt;400 Bad Request&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;BAD_HEADERS
HTTP/1.1 400 Bad Request
content-length: 27

BAD_BODY_PREVIEW
failed to fill whole buffer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The proof server logged the parse failure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Error in response: Error { kind: UnexpectedEof, message: "failed to fill whole buffer" }
POST /check HTTP/1.1; took 0.001360s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Root cause
&lt;/h3&gt;

&lt;p&gt;The request body no longer matched the expected wire format because the payload was truncated.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fix
&lt;/h3&gt;

&lt;p&gt;Send the original binary payload generated by the Midnight tooling. Keep the content type as &lt;code&gt;application/octet-stream&lt;/code&gt;, and use &lt;code&gt;--data-binary&lt;/code&gt; when testing with &lt;code&gt;curl&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Verify the fix
&lt;/h3&gt;

&lt;p&gt;Resend the unmodified payload:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-sS&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-D&lt;/span&gt; ./evidence/05-fix-good-check.headers.txt &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-o&lt;/span&gt; ./evidence/05-fix-good-check.body.bin &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'Content-Type: application/octet-stream'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--data-binary&lt;/span&gt; @./evidence/05-wire-format-good-check.bin &lt;span class="se"&gt;\&lt;/span&gt;
  http://127.0.0.1:6300/check
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The fixed request returns &lt;code&gt;200 OK&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FIX_GOOD_HEADERS
HTTP/1.1 200 OK
content-length: 30
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Fix a version mismatch between the proof server and the ledger stack
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Symptom
&lt;/h3&gt;

&lt;p&gt;Your local stack is reachable, but proof generation fails after you change the proof server image or a ledger-related package.&lt;/p&gt;

&lt;h3&gt;
  
  
  What to check
&lt;/h3&gt;

&lt;p&gt;Compare the proof server Docker tag with the ledger and runtime packages used by your local DApp.&lt;/p&gt;

&lt;h3&gt;
  
  
  Commands
&lt;/h3&gt;

&lt;p&gt;Inspect the local package versions and proof server image:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm list @midnight-ntwrk/ledger-v8
npm list @midnight-ntwrk/compact-runtime
npm list @midnight-ntwrk/onchain-runtime-v3
docker ps | &lt;span class="nb"&gt;grep &lt;/span&gt;proof-server
docker inspect &lt;span class="nt"&gt;--format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'{{.Config.Image}}'&lt;/span&gt; example-hello-world-proof-server-1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A known-good local stack used &lt;code&gt;@midnight-ntwrk/ledger-v8@8.0.3&lt;/code&gt; with this proof server image:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;midnightntwrk/proof-server:8.0.3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To reproduce a mismatch, I changed the proof server image to an older major version:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;image: 'midnightntwrk/proof-server:7.0.0'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then I ran the same local test flow again.&lt;/p&gt;

&lt;h3&gt;
  
  
  What the logs show
&lt;/h3&gt;

&lt;p&gt;The mismatched proof server accepted traffic, but proof generation failed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;× Hello World Contract &amp;gt; Deploys the contract 301111ms
  → Failed to prove transaction

(FiberFailure) Wallet.Proving: Failed to prove transaction
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The proof server logs showed that the failing run reached &lt;code&gt;/prove&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GET /version HTTP/1.1; took 0.008403s
Starting to process request for /prove...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Root cause
&lt;/h3&gt;

&lt;p&gt;The proof server image did not match the local ledger stack. The server was reachable, but the proof path was not compatible with the versions used by the DApp and wallet stack.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fix
&lt;/h3&gt;

&lt;p&gt;Restore the proof server image to the version that matches the local ledger packages:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;image: 'midnightntwrk/proof-server:8.0.3'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Restart the local stack with the same startup command used by your project.&lt;/p&gt;

&lt;h3&gt;
  
  
  Verify the fix
&lt;/h3&gt;

&lt;p&gt;Run the same local test flow again. The aligned stack should pass:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;✓ Hello World Contract &amp;gt; Deploys the contract
✓ Hello World Contract &amp;gt; Stores Hello World!

Test Files  1 passed (1)
Tests       2 passed (2)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One important note: an older patch tag did not fail in this setup. Do not assume every older proof server tag reproduces a mismatch. Use the supported version set for your stack and verify with a real proof-generating flow.&lt;/p&gt;

&lt;h2&gt;
  
  
  Proof server liveness checklist
&lt;/h2&gt;

&lt;p&gt;Use this checklist before changing DApp code:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;docker ps&lt;/code&gt; shows the proof server container running.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;curl -i http://localhost:6300/version&lt;/code&gt; returns &lt;code&gt;HTTP/1.1 200 OK&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The response body includes the proof server version, for example &lt;code&gt;8.0.3&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;docker logs&lt;/code&gt; shows the service listening on &lt;code&gt;0.0.0.0:6300&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Cold startup logs may show missing public parameters or zero-knowledge proving keys being downloaded and verified.&lt;/li&gt;
&lt;li&gt;A low timeout can fail even when the proof server is healthy.&lt;/li&gt;
&lt;li&gt;A Docker health status can be misleading if the container health check depends on a tool that is missing inside the container.&lt;/li&gt;
&lt;li&gt;The proof server Docker tag matches the ledger version used by the local stack.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/check&lt;/code&gt; and &lt;code&gt;/prove&lt;/code&gt; requests use the correct binary wire format.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Wrap up
&lt;/h2&gt;

&lt;p&gt;When proof generation fails, start with the &lt;code&gt;/version&lt;/code&gt; liveness check, then inspect Docker logs, and then identify the exact failure boundary. A connection failure, an abort timeout, a rejected binary payload, and a version mismatch can look similar from a DApp, but they leave different signals in the proof server logs.&lt;/p&gt;

</description>
      <category>backend</category>
      <category>blockchain</category>
      <category>tutorial</category>
      <category>web3</category>
    </item>
    <item>
      <title>Decoding error 1010 on Midnight: What "Invalid Transaction" actually means</title>
      <dc:creator>cobra</dc:creator>
      <pubDate>Mon, 15 Jun 2026 14:16:35 +0000</pubDate>
      <link>https://dev.to/cobra1/decoding-error-1010-on-midnight-what-invalid-transaction-actually-means-5ecc</link>
      <guid>https://dev.to/cobra1/decoding-error-1010-on-midnight-what-invalid-transaction-actually-means-5ecc</guid>
      <description>&lt;h2&gt;
  
  
  What this guide covers
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;1010: Invalid Transaction&lt;/code&gt; often leaves Midnight developers with an error that is too generic to fix on its own. In most cases, &lt;code&gt;1010&lt;/code&gt; is the outer JSON-RPC / author-RPC error, not the full diagnosis. The more useful clue is often in &lt;code&gt;error.data&lt;/code&gt;, such as &lt;code&gt;Custom error: 186&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The sections below explain the &lt;code&gt;1010&lt;/code&gt; error structure, how to read &lt;code&gt;Custom error: N&lt;/code&gt;, how to interpret custom codes &lt;code&gt;139&lt;/code&gt;, &lt;code&gt;154&lt;/code&gt;, &lt;code&gt;168&lt;/code&gt;, &lt;code&gt;170&lt;/code&gt;, and &lt;code&gt;186&lt;/code&gt;, and how Midnight’s five-dimensional ledger cost model relates to block-limit diagnosis.&lt;/p&gt;

&lt;h2&gt;
  
  
  Scope and evidence basis
&lt;/h2&gt;

&lt;p&gt;This is a source-backed diagnostic tutorial. It focuses on decoding &lt;code&gt;1010: Invalid Transaction&lt;/code&gt;, interpreting &lt;code&gt;Custom error: N&lt;/code&gt;, mapping custom codes &lt;code&gt;139&lt;/code&gt;, &lt;code&gt;154&lt;/code&gt;, &lt;code&gt;168&lt;/code&gt;, &lt;code&gt;170&lt;/code&gt;, and &lt;code&gt;186&lt;/code&gt;, and explaining how Midnight’s five-dimensional ledger cost model affects block-limit diagnosis.&lt;/p&gt;

&lt;p&gt;The mappings and worked examples here are based on public Midnight source code, documentation, forum discussions, and issue threads linked throughout the guide and in the Sources checked section. None of the five custom-code failure paths was reproduced first-hand by the author. Any local command output used during research was limited to basic tooling capture, not end-to-end reproduction of these failures.&lt;/p&gt;

&lt;h2&gt;
  
  
  Verification date and version scope
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Verification date:&lt;/strong&gt; May 10, 2026&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sources and version scope reverified:&lt;/strong&gt; June 15, 2026&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Runtime mapping source:&lt;/strong&gt; &lt;a href="https://github.com/midnightntwrk/midnight-node/blob/948b7dbcd975ce5a360d83f6353c2b4872482621/ledger/src/versions/common/types.rs" rel="noopener noreferrer"&gt;&lt;code&gt;midnight-node&lt;/code&gt; commit &lt;code&gt;948b7dbcd975ce5a360d83f6353c2b4872482621&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Issue #667 reported versions:&lt;/strong&gt; Compact compiler &lt;code&gt;0.29.0&lt;/code&gt; / &lt;code&gt;0.30.0-rc.0&lt;/code&gt;, &lt;code&gt;compact-js 2.5.0&lt;/code&gt;, and &lt;code&gt;ledger-v8 8.0.0&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Issue #731 reported versions:&lt;/strong&gt; Midnight.js packages &lt;code&gt;4.0.2&lt;/code&gt;, &lt;code&gt;ledger-v8 8.0.3&lt;/code&gt;, &lt;code&gt;compact-js 2.5.0&lt;/code&gt;, Compact runtime &lt;code&gt;0.15.0&lt;/code&gt;, &lt;code&gt;compactc 0.30.0&lt;/code&gt;, proof server &lt;code&gt;8.0.3&lt;/code&gt;, and the preview network after the March 25, 2026 reset&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The numeric mappings in this guide are version-specific. Verify them against the &lt;code&gt;midnight-node&lt;/code&gt; and ledger versions used by your application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;Start by capturing the full error returned by your wallet, toolkit, DApp, or JSON-RPC client. The most useful fields are &lt;code&gt;error.code&lt;/code&gt;, &lt;code&gt;error.message&lt;/code&gt;, and &lt;code&gt;error.data&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you are debugging a local setup, also record your package versions, target network, node status, and indexer status if the transaction produced a hash. Include proof server status only if the failing flow depends on proof generation. Do not start by changing smart contract code from the number &lt;code&gt;1010&lt;/code&gt; alone.&lt;/p&gt;

&lt;h2&gt;
  
  
  Error 1010 is not the whole diagnosis
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;1010: Invalid Transaction&lt;/code&gt; is best treated as a two-layer error.&lt;/p&gt;

&lt;p&gt;The outer layer is the JSON-RPC / author-RPC invalid transaction error. It tells you that the transaction was rejected as invalid by the submission path, but it is usually not specific enough to explain why.&lt;/p&gt;

&lt;p&gt;The inner layer is the diagnostic detail, which often appears in &lt;code&gt;error.data&lt;/code&gt;. Depending on the failure, &lt;code&gt;error.data&lt;/code&gt; may contain a built-in invalid transaction reason or a Midnight runtime custom code such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"code"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1010&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Invalid Transaction"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Custom error: 186"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case, &lt;code&gt;1010&lt;/code&gt; tells you the transaction was rejected as invalid. &lt;code&gt;Custom error: 186&lt;/code&gt; tells you where to investigate next.&lt;/p&gt;

&lt;p&gt;This distinction matters because the same outer error can point to very different underlying problems, including block-limit pressure, malformed transaction effects, or fee-calculation and builder-side issues.&lt;/p&gt;

&lt;h2&gt;
  
  
  How the 1010 error structure works
&lt;/h2&gt;

&lt;p&gt;The outer invalid-transaction code comes from the upstream author-RPC error mapping. In the shorthand often used for this error family, &lt;code&gt;AUTHOR(1000)&lt;/code&gt; refers to the author-RPC error family whose base value is &lt;code&gt;1000&lt;/code&gt;; &lt;code&gt;POOL_INVALID_TX&lt;/code&gt; adds &lt;code&gt;10&lt;/code&gt; to that base, producing &lt;code&gt;1010&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;BASE_ERROR = 1000
POOL_INVALID_TX = BASE_ERROR + 10
1000 + 10 = 1010
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So &lt;code&gt;1010&lt;/code&gt; is the outer invalid-transaction wrapper. It is not a Midnight-specific custom code by itself.&lt;/p&gt;

&lt;p&gt;The custom part, when present, appears inside &lt;code&gt;error.data&lt;/code&gt; as decimal text:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Custom error: N
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That &lt;code&gt;N&lt;/code&gt; is the value to map against Midnight’s runtime custom-code mapping. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Custom error: 186
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;should be investigated as code &lt;code&gt;186&lt;/code&gt;, not as generic &lt;code&gt;1010&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Also note that not every &lt;code&gt;1010&lt;/code&gt; has to be a &lt;code&gt;Custom error: N&lt;/code&gt; case. Some failures can appear as built-in invalid transaction reasons. For block-limit diagnosis, this matters because a transaction may be rejected through a block-exhaustion path and still appear under the outer &lt;code&gt;1010&lt;/code&gt; invalid-transaction error.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to find the inner custom code
&lt;/h2&gt;

&lt;p&gt;When you see &lt;code&gt;1010: Invalid Transaction&lt;/code&gt;, do this before changing code:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Capture the full JSON-RPC error.&lt;/li&gt;
&lt;li&gt;Record &lt;code&gt;error.code&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Record &lt;code&gt;error.message&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Record &lt;code&gt;error.data&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Check whether &lt;code&gt;error.data&lt;/code&gt; contains a built-in invalid transaction reason or &lt;code&gt;Custom error: N&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;If it contains &lt;code&gt;Custom error: N&lt;/code&gt;, map &lt;code&gt;N&lt;/code&gt; using the code table below.&lt;/li&gt;
&lt;li&gt;Check wallet, toolkit, builder, node, or indexer logs where they are relevant to the failure. Include proof server logs only if the failing flow depends on proof generation.&lt;/li&gt;
&lt;li&gt;Reduce the failing action to the smallest transaction, circuit call, or deployment that still fails.&lt;/li&gt;
&lt;li&gt;Re-run after the targeted fix and compare before-and-after evidence.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The main rule is simple: do not diagnose from &lt;code&gt;1010&lt;/code&gt; alone. Diagnose from the inner detail.&lt;/p&gt;

&lt;h3&gt;
  
  
  Worked example: reading the useful part of the error
&lt;/h3&gt;

&lt;p&gt;Suppose your client shows this error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"code"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1010&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Invalid Transaction"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Custom error: 186"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Read it in two passes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;code: 1010&lt;/code&gt; means the transaction was rejected as invalid by the submission path.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;data: "Custom error: 186"&lt;/code&gt; is the part to investigate next.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Using the code map below, treat &lt;code&gt;186&lt;/code&gt; as an effects-check failure, so the next question is not “why did JSON-RPC return 1010?” It is whether the transaction’s declared effects match the effects the ledger computes during validation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Code map: 139, 154, 168, 170, and 186
&lt;/h2&gt;

&lt;p&gt;This guide focuses on five custom codes that are especially useful when diagnosing &lt;code&gt;1010: Invalid Transaction&lt;/code&gt;: &lt;code&gt;139&lt;/code&gt;, &lt;code&gt;154&lt;/code&gt;, &lt;code&gt;168&lt;/code&gt;, &lt;code&gt;170&lt;/code&gt;, and &lt;code&gt;186&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The source-defined mappings below are verified against the &lt;a href="https://github.com/midnightntwrk/midnight-node/blob/948b7dbcd975ce5a360d83f6353c2b4872482621/ledger/src/versions/common/types.rs" rel="noopener noreferrer"&gt;&lt;code&gt;midnight-node&lt;/code&gt; runtime custom-code mapping at commit &lt;code&gt;948b7dbcd975ce5a360d83f6353c2b4872482621&lt;/code&gt;&lt;/a&gt;. The table separates the exact runtime mapping from the practical area to investigate. These mappings are version-specific, so check the source for the exact Midnight version you are running.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Code&lt;/th&gt;
&lt;th&gt;Source-defined runtime mapping&lt;/th&gt;
&lt;th&gt;First thing to suspect&lt;/th&gt;
&lt;th&gt;Practical diagnostic area&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;139&lt;/td&gt;
&lt;td&gt;&lt;code&gt;MalformedError::UnknownError&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;the number alone is not specific enough&lt;/td&gt;
&lt;td&gt;inspect wallet, toolkit, builder, and fee-calculation logs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;154&lt;/td&gt;
&lt;td&gt;&lt;code&gt;LedgerApiError::BlockLimitExceededError&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;transaction or deployment pressure against block limits&lt;/td&gt;
&lt;td&gt;check transaction size, deployment size, and cost-model pressure&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;168&lt;/td&gt;
&lt;td&gt;&lt;code&gt;MalformedError::FeeCalculation&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;fee calculation or transaction assembly&lt;/td&gt;
&lt;td&gt;inspect fee calculation, balancing, transcript partitioning, settlement, and transaction-assembly logs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;170&lt;/td&gt;
&lt;td&gt;&lt;code&gt;MalformedError::InvalidDustSpendProof&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;an invalid or stale DUST spend proof&lt;/td&gt;
&lt;td&gt;inspect DUST proof validity, Merkle-root freshness, and witness freshness&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;186&lt;/td&gt;
&lt;td&gt;&lt;code&gt;MalformedError::EffectsCheckFailure&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;declared effects do not match ledger-computed effects&lt;/td&gt;
&lt;td&gt;inspect the mismatch between declared and computed transaction effects&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h3&gt;
  
  
  Evidence and reproduction status
&lt;/h3&gt;

&lt;p&gt;The runtime mappings below are verified from the pinned &lt;code&gt;midnight-node&lt;/code&gt; source. “Not reproduced” means the author did not personally trigger and capture that error in a local or network transaction.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Code&lt;/th&gt;
      &lt;th&gt;Evidence basis&lt;/th&gt;
      &lt;th&gt;First-hand reproduction&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;th&gt;139&lt;/th&gt;
      &lt;td&gt;
        &lt;a href="https://github.com/midnightntwrk/midnight-node/blob/948b7dbcd975ce5a360d83f6353c2b4872482621/ledger/src/versions/common/types.rs" rel="noopener noreferrer"&gt;Pinned runtime source&lt;/a&gt;
        and
        &lt;a href="https://github.com/midnightntwrk/midnight-js/issues/667" rel="noopener noreferrer"&gt;Midnight.js issue #667&lt;/a&gt;
      &lt;/td&gt;
      &lt;td rowspan="5"&gt;
        No. All five mappings are source-backed; none was reproduced first-hand by author.
      &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;154&lt;/th&gt;
      &lt;td&gt;
        &lt;a href="https://github.com/midnightntwrk/midnight-node/blob/948b7dbcd975ce5a360d83f6353c2b4872482621/ledger/src/versions/common/types.rs" rel="noopener noreferrer"&gt;Pinned runtime source&lt;/a&gt;
        and public block-limit documentation and discussion
      &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;168&lt;/th&gt;
      &lt;td&gt;
        &lt;a href="https://github.com/midnightntwrk/midnight-node/blob/948b7dbcd975ce5a360d83f6353c2b4872482621/ledger/src/versions/common/types.rs" rel="noopener noreferrer"&gt;Pinned runtime source&lt;/a&gt;;
        practical guidance based on the source-defined
        &lt;code&gt;FeeCalculation&lt;/code&gt; mapping
      &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;170&lt;/th&gt;
      &lt;td&gt;
        &lt;a href="https://github.com/midnightntwrk/midnight-node/blob/948b7dbcd975ce5a360d83f6353c2b4872482621/ledger/src/versions/common/types.rs" rel="noopener noreferrer"&gt;Pinned runtime source&lt;/a&gt;;
        practical guidance based on the source-defined
        &lt;code&gt;InvalidDustSpendProof&lt;/code&gt; mapping
      &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;th&gt;186&lt;/th&gt;
      &lt;td&gt;
        &lt;a href="https://github.com/midnightntwrk/midnight-node/blob/948b7dbcd975ce5a360d83f6353c2b4872482621/ledger/src/versions/common/types.rs" rel="noopener noreferrer"&gt;Pinned runtime source&lt;/a&gt;,
        &lt;a href="https://github.com/midnightntwrk/midnight-js/issues/731" rel="noopener noreferrer"&gt;Midnight.js issue #731&lt;/a&gt;,
        and its
        &lt;a href="https://github.com/adamreynolds-io/issue-731-validation/blob/main/README.md" rel="noopener noreferrer"&gt;validation repository&lt;/a&gt;
      &lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Quick diagnostic matrix
&lt;/h2&gt;

&lt;p&gt;Use this table for a first-pass triage after you identify the inner custom code.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;If you see&lt;/th&gt;
&lt;th&gt;First place to look&lt;/th&gt;
&lt;th&gt;Why&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Custom error: 139&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;wallet/toolkit/builder logs&lt;/td&gt;
&lt;td&gt;the number alone may not identify the final root cause&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Custom error: 154&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;transaction size, deployment size, cost pressure&lt;/td&gt;
&lt;td&gt;the transaction may be pushing against block limits&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Custom error: 168&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;batch settlement, fee calculation, balancing&lt;/td&gt;
&lt;td&gt;this often points to a settlement-adjacent transaction assembly path&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Custom error: 170&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Merkle-root freshness, DUST spend proof, witness freshness&lt;/td&gt;
&lt;td&gt;stale or pruned root assumptions can surface through the proof/witness path&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Custom error: 186&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;declared vs ledger-computed effects&lt;/td&gt;
&lt;td&gt;the transaction effects may not match what ledger validation computes&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The matrix above is the fast triage view. The sections below explain each code in more detail.&lt;/p&gt;

&lt;h2&gt;
  
  
  Code 139
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What you may see:
&lt;/h3&gt;

&lt;p&gt;A transaction submission fails under outer &lt;code&gt;1010&lt;/code&gt;, with the inner detail showing &lt;code&gt;Custom error: 139&lt;/code&gt;. In practice, developers may first encounter this during transaction construction in builder, wallet, or toolkit flows.&lt;/p&gt;

&lt;h3&gt;
  
  
  What it usually means in practice:
&lt;/h3&gt;

&lt;p&gt;At the pinned runtime version, code &lt;code&gt;139&lt;/code&gt; maps to &lt;code&gt;MalformedError::UnknownError&lt;/code&gt;. Treat it as a non-specific malformed-transaction signal rather than a final diagnosis. The useful place to look is the surrounding wallet, toolkit, and builder logs.&lt;/p&gt;

&lt;p&gt;In &lt;a href="https://github.com/midnightntwrk/midnight-js/issues/667" rel="noopener noreferrer"&gt;Midnight.js issue #667&lt;/a&gt;, an unshielded NIGHT operation surfaced through RPC as &lt;code&gt;1010: Invalid Transaction: Custom error: 139&lt;/code&gt;, while the more detailed toolkit output identified a fee-calculation rejection. This example shows why you should use &lt;code&gt;139&lt;/code&gt; as a starting point and inspect the surrounding toolchain logs for the more specific failure.&lt;/p&gt;

&lt;h3&gt;
  
  
  First place to check:
&lt;/h3&gt;

&lt;p&gt;Start with wallet, toolkit, builder, and transaction-construction diagnostics. The RPC code may be less specific than the logs produced by the surrounding toolchain.&lt;/p&gt;

&lt;h3&gt;
  
  
  Diagnostic steps:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Capture the full JSON-RPC error and confirm whether &lt;code&gt;error.data&lt;/code&gt; contains &lt;code&gt;Custom error: 139&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Check toolkit, wallet, and builder logs for a more specific malformed-transaction or fee-related diagnostic.&lt;/li&gt;
&lt;li&gt;Review the transaction-construction path that assembled the failing extrinsic.&lt;/li&gt;
&lt;li&gt;Reduce the failing action to the smallest transaction or circuit call that still produces the same inner code.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  What not to assume:
&lt;/h3&gt;

&lt;p&gt;Do not assume that &lt;code&gt;139&lt;/code&gt; by itself proves one exact root cause. Do not present “transaction builder” as the verified public enum name. The safer move is to treat &lt;code&gt;139&lt;/code&gt; as a malformed-transaction signal and use the surrounding toolkit or builder logs for the more useful clue.&lt;/p&gt;

&lt;h2&gt;
  
  
  Code 154
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What you may see:
&lt;/h3&gt;

&lt;p&gt;A transaction fails under outer &lt;code&gt;1010&lt;/code&gt; with a block-limit-style symptom. It may appear as custom &lt;code&gt;154&lt;/code&gt;, or it may appear as a built-in invalid transaction reason such as block exhaustion.&lt;/p&gt;

&lt;h3&gt;
  
  
  What it usually means in practice:
&lt;/h3&gt;

&lt;p&gt;At the pinned runtime version, code &lt;code&gt;154&lt;/code&gt; maps to &lt;code&gt;LedgerApiError::BlockLimitExceededError&lt;/code&gt;. Treat it as a block-limit signal. The transaction, deployment, or state update may be pushing against one or more ledger cost dimensions.&lt;/p&gt;

&lt;p&gt;The useful next step is to inspect transaction size, deployment size, smart contract complexity, and cost-model pressure before assuming the smart contract logic itself is broken.&lt;/p&gt;

&lt;h3&gt;
  
  
  First place to check:
&lt;/h3&gt;

&lt;p&gt;Start with transaction size, deployment size, smart contract complexity, and Midnight’s five-dimensional ledger cost model: &lt;code&gt;readTime&lt;/code&gt;, &lt;code&gt;computeTime&lt;/code&gt;, &lt;code&gt;blockUsage&lt;/code&gt;, &lt;code&gt;bytesWritten&lt;/code&gt;, and &lt;code&gt;bytesChurned&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Diagnostic steps:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Capture the full error and check whether the inner detail is &lt;code&gt;Custom error: 154&lt;/code&gt; or a built-in block-exhaustion reason.&lt;/li&gt;
&lt;li&gt;Inspect whether the failing action is a large deployment, state-heavy update, or complex transaction.&lt;/li&gt;
&lt;li&gt;Check which cost-model dimension is most likely under pressure: reads, compute, block usage, bytes written, or bytes churned.&lt;/li&gt;
&lt;li&gt;Reduce transaction or deployment complexity, then re-run and compare the new error output.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  What not to assume:
&lt;/h3&gt;

&lt;p&gt;Do not assume every block-limit failure appears as custom &lt;code&gt;154&lt;/code&gt;. Some block-limit failures may still be wrapped by outer &lt;code&gt;1010&lt;/code&gt; while surfacing through a built-in invalid transaction path.&lt;/p&gt;

&lt;h2&gt;
  
  
  Code 168
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What you may see:
&lt;/h3&gt;

&lt;p&gt;A transaction fails under outer &lt;code&gt;1010&lt;/code&gt; while the wallet, toolkit, or DApp is assembling a transaction that needs settlement, balancing, or fee calculation. Developers may see this described as a batch-settlement-style failure because the transaction fails while the final transaction package is being assembled or reconciled.&lt;/p&gt;

&lt;h3&gt;
  
  
  What it usually means in practice:
&lt;/h3&gt;

&lt;p&gt;At the pinned runtime version, code &lt;code&gt;168&lt;/code&gt; maps to &lt;code&gt;MalformedError::FeeCalculation&lt;/code&gt;. In practice, inspect the settlement and transaction-assembly path: fee calculation, balancing, transcript partitioning, and how the final transaction package is assembled.&lt;/p&gt;

&lt;p&gt;This is especially relevant when the failing transaction touches NIGHT movement paths such as &lt;code&gt;sendUnshielded&lt;/code&gt; or &lt;code&gt;receiveUnshielded&lt;/code&gt;, because the transaction may fail before the problem looks like a bug in the smart contract.&lt;/p&gt;

&lt;h3&gt;
  
  
  First place to check:
&lt;/h3&gt;

&lt;p&gt;Start with the batch-settlement or transaction-assembly path: fee calculation, balancing behavior, transcript partitioning, and wallet or toolkit diagnostics around how the final transaction was assembled.&lt;/p&gt;

&lt;h3&gt;
  
  
  Diagnostic steps:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Capture the full error and confirm whether the inner detail is &lt;code&gt;Custom error: 168&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Inspect wallet and toolkit logs for settlement, balancing, transcript, or fee-calculation details.&lt;/li&gt;
&lt;li&gt;Review how the final transaction package is assembled, especially where unshielded receive or send paths are involved.&lt;/li&gt;
&lt;li&gt;Reduce the action to the smallest transaction that still exercises the same settlement, balancing, or fee-calculation path.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  What not to assume:
&lt;/h3&gt;

&lt;p&gt;Do not assume that &lt;code&gt;168&lt;/code&gt; proves one exact settlement mechanism or a Compact circuit bug. The safer debugging move is to inspect the batch-settlement, fee-calculation, balancing, and transaction-assembly path before changing smart contract code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Code 170
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What you may see:
&lt;/h3&gt;

&lt;p&gt;A transaction fails under outer &lt;code&gt;1010&lt;/code&gt;, with the inner detail showing &lt;code&gt;Custom error: 170&lt;/code&gt;. The pinned runtime source maps code &lt;code&gt;170&lt;/code&gt; to &lt;code&gt;MalformedError::InvalidDustSpendProof&lt;/code&gt;. Stale or mismatched proof, witness, or state-root data are possible diagnostic areas, not additional source-defined meanings of the code.&lt;/p&gt;

&lt;h3&gt;
  
  
  What it usually means in practice:
&lt;/h3&gt;

&lt;p&gt;At the pinned runtime version, code &lt;code&gt;170&lt;/code&gt; maps to &lt;code&gt;MalformedError::InvalidDustSpendProof&lt;/code&gt;. Treat it as a DUST spend proof failure whose investigation may include Merkle-root and witness freshness. The useful place to look is whether the proof, witness, or state root used to assemble the transaction is stale, mismatched, pruned, or no longer matches the state expected during validation.&lt;/p&gt;

&lt;h3&gt;
  
  
  First place to check:
&lt;/h3&gt;

&lt;p&gt;Start with Merkle-root freshness, DUST spend proof validity, stale proof assumptions, and whether the proof or witness binding still matches the transaction being submitted.&lt;/p&gt;

&lt;h3&gt;
  
  
  Diagnostic steps:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Capture the full error and confirm whether &lt;code&gt;error.data&lt;/code&gt; contains &lt;code&gt;Custom error: 170&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Check whether the failing transaction includes a DUST spend proof, witness, or state-root-dependent path.&lt;/li&gt;
&lt;li&gt;Review whether the proof, witness, Merkle root, and transaction data are stale, pruned, mismatched, or assembled from different states.&lt;/li&gt;
&lt;li&gt;Rebuild the transaction from fresh state where possible, then rerun and compare the before-and-after error data.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  What not to assume:
&lt;/h3&gt;

&lt;p&gt;Do not assume that &lt;code&gt;170&lt;/code&gt; proves one exact pruning trigger or one exact stale-root mechanism. The safer diagnostic area is Merkle-root freshness plus the DUST spend proof path: proof validity, witness freshness, and whether the proof still matches the transaction being submitted.&lt;/p&gt;

&lt;h2&gt;
  
  
  Code 186
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What you may see:
&lt;/h3&gt;

&lt;p&gt;A transaction fails under outer &lt;code&gt;1010&lt;/code&gt;, with the inner detail showing &lt;code&gt;Custom error: 186&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  What it usually means in practice:
&lt;/h3&gt;

&lt;p&gt;At the pinned runtime version, code &lt;code&gt;186&lt;/code&gt; maps to &lt;code&gt;MalformedError::EffectsCheckFailure&lt;/code&gt;. &lt;a href="https://github.com/midnightntwrk/midnight-js/issues/731" rel="noopener noreferrer"&gt;Midnight.js issue #731&lt;/a&gt; documents a &lt;code&gt;1010: Invalid Transaction: Custom error: 186&lt;/code&gt; case involving a circuit that combined &lt;code&gt;mintShieldedToken&lt;/code&gt; with &lt;code&gt;receiveUnshielded&lt;/code&gt;. The transaction was assembled with one set of effects, but the ledger validation path rejected the resulting effects check.&lt;/p&gt;

&lt;p&gt;That means the next debugging step is not the proof server, and not the outer &lt;code&gt;1010&lt;/code&gt; wrapper. The next step is to inspect how the final transaction effects were assembled.&lt;/p&gt;

&lt;h3&gt;
  
  
  First place to check:
&lt;/h3&gt;

&lt;p&gt;Start with the transaction effects. The key question is whether the effects declared by the assembled transaction match the effects computed by the ledger during validation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Diagnostic steps:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Capture the full error and confirm whether &lt;code&gt;error.data&lt;/code&gt; contains &lt;code&gt;Custom error: 186&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Inspect the transaction assembly path for combined actions that may alter the final declared effects.&lt;/li&gt;
&lt;li&gt;Compare the intended effects with the effects the ledger would compute from the final transaction.&lt;/li&gt;
&lt;li&gt;Reduce the failing action to the smallest transaction that still produces the effects-check failure.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  What not to assume:
&lt;/h3&gt;

&lt;p&gt;Do not treat &lt;code&gt;186&lt;/code&gt; as a generic proof-server problem. The useful diagnostic area is effects mismatch: compare the transaction’s declared effects against the effects the ledger computes during validation.&lt;/p&gt;

&lt;p&gt;Block-limit-related failures need one more piece of context: Midnight’s five-dimensional ledger cost model.&lt;/p&gt;

&lt;h2&gt;
  
  
  The five-dimensional ledger cost model
&lt;/h2&gt;

&lt;p&gt;Midnight’s block-limit diagnosis should be understood through its five-dimensional ledger cost model:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;readTime&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;computeTime&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;blockUsage&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;bytesWritten&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;bytesChurned&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The practical model is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;transaction cost = (readTime, computeTime, blockUsage, bytesWritten, bytesChurned)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each dimension is normalized against its corresponding block limit. The dimension with the highest normalized value becomes the main source of pressure. If any dimension exceeds its limit, the transaction can be rejected.&lt;/p&gt;

&lt;p&gt;This matters because a transaction does not need to be “too big” in every way to fail. One dimension can dominate. For example, a deployment might be acceptable in read pressure and compute pressure but fail because &lt;code&gt;bytesWritten&lt;/code&gt; exceeds the allowed limit. Another transaction might have moderate byte size but fail because validation or execution pressure is too high.&lt;/p&gt;

&lt;p&gt;Be careful with exact numbers. Unless you have current network-specific parameters, do not claim exact block-limit thresholds or exact units for every dimension. For diagnostics, the safe lesson is that block-limit failures are measured across five dimensions, and the largest normalized dimension is the one to investigate first.&lt;/p&gt;

&lt;h2&gt;
  
  
  Diagnostic workflow
&lt;/h2&gt;

&lt;p&gt;Use this order when investigating &lt;code&gt;1010: Invalid Transaction&lt;/code&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Capture the full error object.&lt;/li&gt;
&lt;li&gt;Separate the outer &lt;code&gt;1010&lt;/code&gt; wrapper from the inner detail.&lt;/li&gt;
&lt;li&gt;Look for &lt;code&gt;error.data&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Decide whether &lt;code&gt;error.data&lt;/code&gt; is a built-in invalid transaction reason or &lt;code&gt;Custom error: N&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;If you have &lt;code&gt;Custom error: N&lt;/code&gt;, map &lt;code&gt;N&lt;/code&gt; to the code table.&lt;/li&gt;
&lt;li&gt;Record package versions, tooling versions, and target network.&lt;/li&gt;
&lt;li&gt;Check toolkit, wallet, builder, node, and indexer logs where relevant. Include proof server logs only if the failing flow depends on proof generation.&lt;/li&gt;
&lt;li&gt;Reduce the failing action to the smallest transaction, circuit call, or deployment that still fails.&lt;/li&gt;
&lt;li&gt;Apply a targeted fix based on the mapped failure family.&lt;/li&gt;
&lt;li&gt;Re-run and compare the before-and-after evidence.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The most important habit is to preserve the full error before changing anything. A screenshot or copied line that only says &lt;code&gt;1010&lt;/code&gt; is usually not enough.&lt;/p&gt;

&lt;h2&gt;
  
  
  Evidence to capture before asking for help
&lt;/h2&gt;

&lt;p&gt;Before posting in a forum, Discord, or GitHub issue, capture:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;full JSON-RPC error&lt;/li&gt;
&lt;li&gt;&lt;code&gt;error.code&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;error.message&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;error.data&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;custom code, if present&lt;/li&gt;
&lt;li&gt;package versions&lt;/li&gt;
&lt;li&gt;network used&lt;/li&gt;
&lt;li&gt;transaction hash, if available&lt;/li&gt;
&lt;li&gt;wallet/toolkit logs&lt;/li&gt;
&lt;li&gt;node logs, if relevant&lt;/li&gt;
&lt;li&gt;proof server status, only if the failing flow depends on proof generation&lt;/li&gt;
&lt;li&gt;indexer status, if relevant&lt;/li&gt;
&lt;li&gt;smallest failing smart contract, circuit, deployment, or action&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This evidence helps others distinguish between transaction-construction issues, fee calculation, block-limit pressure, invalid DUST spend proof, and effects-check mismatch.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sources checked
&lt;/h2&gt;

&lt;p&gt;This guide is based on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://crates.parity.io/src/sc_rpc_api/author/error.rs.html" rel="noopener noreferrer"&gt;Substrate author-RPC error handling&lt;/a&gt;, which defines the upstream &lt;code&gt;BASE_ERROR = 1000&lt;/code&gt; and &lt;code&gt;POOL_INVALID_TX = BASE_ERROR + 10&lt;/code&gt; mapping.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.midnight.network/concepts/network-architecture/rpc-networking" rel="noopener noreferrer"&gt;Midnight RPC and networking documentation&lt;/a&gt;, which documents Midnight’s JSON-RPC surface and Polkadot SDK RPC support.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/midnightntwrk/midnight-node/blob/948b7dbcd975ce5a360d83f6353c2b4872482621/ledger/src/versions/common/types.rs" rel="noopener noreferrer"&gt;Midnight runtime custom-code mapping in &lt;code&gt;midnight-node&lt;/code&gt;, pinned to commit &lt;code&gt;948b7dbcd975ce5a360d83f6353c2b4872482621&lt;/code&gt;&lt;/a&gt;, which defines the mappings for codes &lt;code&gt;139&lt;/code&gt;, &lt;code&gt;154&lt;/code&gt;, &lt;code&gt;168&lt;/code&gt;, &lt;code&gt;170&lt;/code&gt;, and &lt;code&gt;186&lt;/code&gt; used in this guide.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.midnight.network/api-reference/ledger/classes/TransactionCostModel" rel="noopener noreferrer"&gt;Midnight ledger &lt;code&gt;TransactionCostModel&lt;/code&gt; documentation&lt;/a&gt;, which documents the cost-model API used for transaction cost and block-limit reasoning.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://forum.midnight.network/t/block-limit-exceeded-1010-when-deploying-contracts-with-many-circuits/1025" rel="noopener noreferrer"&gt;Midnight forum thread on block-limit exhaustion&lt;/a&gt;, which discusses &lt;code&gt;1010&lt;/code&gt; behavior when contract deployment exceeds block limits and names the five cost dimensions used in the block-fullness model.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/midnightntwrk/midnight-js/issues/667" rel="noopener noreferrer"&gt;Midnight.js issue #667&lt;/a&gt;, which shows a real &lt;code&gt;1010&lt;/code&gt; / custom-code debugging case around unshielded NIGHT token operations and fee calculation.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/midnightntwrk/midnight-js/issues/731" rel="noopener noreferrer"&gt;Midnight.js issue #731&lt;/a&gt;, which documents a &lt;code&gt;Custom error: 186&lt;/code&gt; effects-check failure case.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/adamreynolds-io/issue-731-validation/blob/main/README.md" rel="noopener noreferrer"&gt;Issue #731 validation repository&lt;/a&gt;, which provides supporting validation notes for the &lt;code&gt;186&lt;/code&gt; repro family.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Final checklist
&lt;/h2&gt;

&lt;p&gt;When debugging &lt;code&gt;1010: Invalid Transaction&lt;/code&gt;, ask:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Did I capture the full error object?&lt;/li&gt;
&lt;li&gt;Did I inspect &lt;code&gt;error.data&lt;/code&gt;?&lt;/li&gt;
&lt;li&gt;Is this a built-in invalid transaction reason or &lt;code&gt;Custom error: N&lt;/code&gt;?&lt;/li&gt;
&lt;li&gt;Did I use the custom code to choose the right first place to investigate?&lt;/li&gt;
&lt;li&gt;Am I accidentally treating &lt;code&gt;1010&lt;/code&gt; as the root cause?&lt;/li&gt;
&lt;li&gt;Am I overclaiming what the custom code proves before checking logs and version-specific mappings?&lt;/li&gt;
&lt;li&gt;Could this be a five-dimensional cost-model / block-limit problem?&lt;/li&gt;
&lt;li&gt;Have I reduced the failing action to the smallest reproducible case?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The core rule is simple: &lt;code&gt;1010&lt;/code&gt; tells you the transaction was rejected. The inner detail tells you where to look next.&lt;/p&gt;

</description>
      <category>api</category>
      <category>blockchain</category>
      <category>tutorial</category>
      <category>web3</category>
    </item>
  </channel>
</rss>
