A useful error investigation starts with the complete result, the exact transaction and the program version that executed it. Save those before changing inputs. A number such as 6000 has meaning only in the error namespace of the relevant program.
Identify which stage produced the error
A wallet can reject signing before submission. An RPC can reject a malformed request or fail a preflight check. A submitted transaction can later fail during program execution. A timeout can leave the result unknown.
Record the cluster, signature if one exists, serialized transaction or construction inputs, and the response you received. A simulation failure is evidence about that simulated execution. An accepted transaction's metadata records the execution that actually occurred.
Do not treat a simulation log as proof that money moved. Likewise, a successful submission response establishes neither program success nor the final account state. Fetch the outcome under the current documented commitment policy.
Read the outer instruction index
Consider this schematic result:
{"InstructionError": [2, {"Custom": 6000}]}
The index is zero-based: the failure belongs to the third top-level instruction in the transaction. If the first two instructions configure resources or create accounts, counting only the user-visible swap steps can point you to the wrong action.
Decode the actual message's instruction list and complete account references. Versioned messages may require address resolution under their format. Preserve the account ordering used by each instruction; changing it while debugging changes the experiment.
The index identifies the top-level boundary. A program invoked from that instruction can still be the source of the underlying error.
Follow the nested call frames
Logs commonly show program invocation, depth and a success or failure return. Read them as a call tree, not as a flat list of unrelated status lines. A parent program may call a token program or another application through CPI and then return the failure upward.
A line saying an inner call succeeded does not prove the overall transaction succeeded. A later instruction or parent check can fail, causing ordinary state changes from the transaction to roll back while processing fees remain charged.
Use the runtime result and account movements alongside logs. A program can emit descriptive text of its own, and providers can truncate output. An absent message is not proof that a branch never ran.
Decode the number before naming its meaning
Resolve custom codes against the correct program
In Anchor, custom application errors commonly start at 6000, while framework errors occupy other ranges. The hexadecimal representation 0x1770 is decimal 6000. That conversion tells you the number, not its business meaning.
Look up the code in the program's matching IDL or source and confirm the deployed program identity and release. Two programs can both use 6000 for unrelated conditions. A current repository branch can also differ from the artifact used by an older transaction.
If a log names an account constraint, examine the named account relationship. If it reports a mint mismatch, compare the actual mint addresses. If it reports an arithmetic or price-bound error, reproduce the relevant raw inputs and units. Avoid turning a guessed translation into a definitive explanation for users.
Change one failing condition
Build a minimal reproduction with the same program, account types, instruction data and relevant state assumptions. Use a local or development environment and non-production keys for active experiments. Keep each original response so you can explain what changed.
A missing signer needs the correct authorization path. An owner or PDA mismatch needs the expected account relationship. An exhausted compute budget needs measurement of the work and the transaction format's configuration. Increasing priority payment does not change a program's validation rule.
Simulation can help examine a revised attempt, but the state can change before later execution. Inspect the accepted result again after any real submission. A different blockhash or fee setting also creates a different signed attempt to track.
Write an error report another builder can use
Include the public signature, network, top-level instruction index, deepest identifiable failing program, decoded code with its source version and relevant non-secret inputs. State whether the result came from simulation or accepted execution.
If you cannot identify the deployed error mapping, preserve that gap instead of guessing a label. A precise report such as “third instruction, program P, custom 6000, IDL version unavailable” gives the next investigator a useful starting point.
Sources and documentation
- getTransaction
- simulateTransaction
- Transaction structure
- Solana cross-program invocations
- Anchor: error categories and custom errors
- Solana fee calculation and distribution
Found an error or an outdated detail? Send a correction.
