Find the failing instruction in a Solana transaction simulation

A swap builder reports a custom program error. Replaying the serialized transaction with simulateTransaction can identify the outer instruction and the program that emitted the error.

Reproduce the instruction path

Replace BASE64_TRANSACTION with the complete serialized transaction encoded in base64, including its signatures array. POST the body to an HTTP endpoint on the same cluster. This configuration lets the node replace a stale recent blockhash and simulate without checking signatures.

{"jsonrpc":"2.0","id":1,"method":"simulateTransaction","params":["BASE64_TRANSACTION",{"encoding":"base64","commitment":"confirmed","replaceRecentBlockhash":true,"sigVerify":false}]}

For a signature check, use the originally signed bytes with a still-valid blockhash, set sigVerify to true and turn off blockhash replacement. Changing a signed message also changes the data over which its signatures verify.

Trace the instruction and its nested calls

An illustrative value.err is {"InstructionError":[2,{"Custom":6001}]}. Index 2 points to the third top-level instruction in the message. Include compute-budget instructions when counting. In value.logs, follow the nested program invocations surrounding the first failure. Decode 6001 against the error definitions for the program that raised it. Different programs can use the same number.

Record enough evidence for a second run

Keep context.slot, err, logs and unitsConsumed together with the transaction’s instruction list. If you change the accounts or instruction data, compare both runs at recorded slots. A successful simulation describes execution against the sampled state. The account state and available liquidity may change before an actual send.

Solana documentation