Key takeaways
- On Solana, custom program error 0x1 means insufficient funds in both the System program (ResultWithNegativeLamports) and the SPL Token program (InsufficientFunds), but other programs use 0x1 for unrelated errors.
- Custom program error 0x1771 is decimal 6001, the second custom error of an Anchor program: SlippageToleranceExceeded in Jupiter v6, AlreadyInitialized in pump.fun and InvalidOwner in Raydium CPMM.
- Anchor programs number their own errors from 6000 (0x1770), while Anchor's built-in errors sit below that, such as 2000 ConstraintMut and 3012 AccountNotInitialized.
- The number in 'Error processing Instruction 2' is a zero-based index, so it points to the third instruction in the transaction, which in a swap is often the call after two Compute Budget instructions.
- SOLTidy's free Transaction Decoder reads the failing program from the logs and translates known System, SPL Token, Token-2022 and Jupiter error codes without connecting a wallet.
The short answer
A Solana custom program error is a number chosen by the program that failed, shown in hex in the logs, so custom program error: 0x1 and 0x1771 only make sense once you know which program raised them. In the System program 0x1 is ResultWithNegativeLamports (not enough SOL), and in SPL Token and Token-2022 it is InsufficientFunds (not enough tokens). 0x1771 is decimal 6001, the second custom error of an Anchor program, which in Jupiter v6 is SlippageToleranceExceeded. The tables below list every code of the core programs, checked against their source code as of November 2026.
This page is the lookup reference. For the story of why transactions fail and the most common fixes, read why Solana transactions fail first.
How do you read "custom program error: 0x1"?
You read it in three steps: find which program failed, convert the hex code to decimal, and look the number up in that program's error list. A typical failed transaction gives you two pieces of text. The transaction error, as an RPC node or explorer returns it, looks like this:
Error processing Instruction 2: custom program error: 0x1771
{"InstructionError":[2,{"Custom":6001}]}
The program logs carry the third piece, the program that raised it:
Program JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4 invoke [1]
Program log: AnchorError occurred. Error Code: SlippageToleranceExceeded. Error Number: 6001. Error Message: Slippage tolerance exceeded.
Program JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4 failed: custom program error: 0x1771
Each part means something specific:
- The instruction index.
Instruction 2is a zero-based index into the transaction's top-level instructions, so it is the third one. Wallet and app transactions usually start with two Compute Budget instructions (set compute unit limit, set compute unit price), so index 2 is often the first instruction that does real work. - The custom code.
Customis the program's own error number. The JSON form shows it in decimal (6001) and the log line in hex (0x1771); they are the same number. The runtime formats it ascustom program error: {num:#x}in the InstructionError source. - The failing program. The line
Program <address> failed: ...names the program. If one program called another (a cross-program invocation), the inner failure propagates upward, because a calling program cannot catch it. You then see several "failed" lines with the same code, and the first one, the deepest, is the program that raised the error.
Here is the procedure in order:
- Copy the transaction signature from your wallet's activity list or an explorer such as Solscan, Solana Explorer or SolanaFM.
- Open the transaction's logs, or paste the signature into the free Transaction Decoder, which needs no wallet.
- Find the first line containing
failed:and note the program address on it. - Convert the hex code to decimal (next section).
- Look the number up in the table for that program below. Anchor programs often print the error name in a
Program log: AnchorError occurredline, which saves the lookup.
I built the decoder to do steps 3 to 5 automatically: it searches the logs for the first Program ... failed: custom program error line, reports the instruction number counting from one, and adds a plain-English meaning for the System, SPL Token, Token-2022 and Jupiter v6 codes it knows. For other programs it gives you the decimal and hex codes and the program name, and you finish the lookup in that program's IDL.
How do you convert a Solana error code from hex to decimal?
Drop the 0x and read the remaining digits as base 16. Each digit is worth 16 times the one to its right, so 0x1771 is 1 x 4096 + 7 x 256 + 7 x 16 + 1 = 6001. Quick ways to do it:
- Browser console:
parseInt("1771", 16)returns 6001. - Python:
int("1771", 16). - Terminal:
printf "%d\n" 0x1771.
The conversions you will meet most often:
| Hex | Decimal | Where it usually comes from |
|---|---|---|
| 0x0 | 0 | System AccountAlreadyInUse, Token NotRentExempt |
| 0x1 | 1 | System ResultWithNegativeLamports, Token InsufficientFunds |
| 0xb | 11 | Token NonNativeHasBalance (close with tokens left) |
| 0x11 | 17 | Token AccountFrozen |
| 0x1e | 30 | Raydium AMM v4 ExceededSlippage |
| 0x23 | 35 | Token-2022 AccountHasWithheldTransferFees |
| 0x7d0 | 2000 | Anchor ConstraintMut |
| 0xbc4 | 3012 | Anchor AccountNotInitialized |
| 0x1770 | 6000 | First custom error of any Anchor program |
| 0x1771 | 6001 | Second custom error of any Anchor program |
| 0x1772 | 6002 | Third custom error (pump.fun TooMuchSolRequired) |
What do the SPL Token program error codes mean?
SPL Token error codes run from 0x0 to 0x13 (0 to 19) and come from the TokenError enum, numbered in declaration order. The list below is taken from the token program's error.rs, which also defines the "Error:" text the program writes to the logs. The program is TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA, and Token-2022 (TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb) uses the same 20 codes with the same meaning.
| Hex | Dec | Name | Log text | What it means and the fix |
|---|---|---|---|---|
| 0x0 | 0 | NotRentExempt | Lamport balance below rent-exempt threshold | The new account was not funded to its rent-exempt minimum. Fund it with the full deposit; the rent calculator gives the amount |
| 0x1 | 1 | InsufficientFunds | insufficient funds | The token account holds fewer tokens than the amount sent. Check the balance and the decimals |
| 0x2 | 2 | InvalidMint | Invalid Mint | The mint account is not a valid, initialized mint |
| 0x3 | 3 | MintMismatch | Account not associated with this Mint | The token account belongs to a different mint than the instruction expects |
| 0x4 | 4 | OwnerMismatch | owner does not match | The signer is not the account owner, delegate or close authority. Sign with the right wallet |
| 0x5 | 5 | FixedSupply | the total supply of this token is fixed | Minting was attempted after the mint authority was revoked |
| 0x6 | 6 | AlreadyInUse | account or token already in use | The account being initialized is already initialized |
| 0x7 | 7 | InvalidNumberOfProvidedSigners | Invalid number of provided signers | A multisig got the wrong number of signer accounts |
| 0x8 | 8 | InvalidNumberOfRequiredSigners | Invalid number of required signers | A multisig was configured with an invalid threshold |
| 0x9 | 9 | UninitializedState | State is uninitialized | The token account or mint does not exist yet. Create it first |
| 0xa | 10 | NativeNotSupported | Instruction does not support native tokens | The instruction cannot be used on a wrapped SOL account |
| 0xb | 11 | NonNativeHasBalance | Non-native account can only be closed if its balance is zero | Closing an account that still holds tokens. Sell, send or burn them first |
| 0xc | 12 | InvalidInstruction | Invalid instruction | The instruction data could not be parsed |
| 0xd | 13 | InvalidState | Invalid account state for operation | The account is in a state that does not allow this operation |
| 0xe | 14 | Overflow | Operation overflowed | An amount calculation overflowed, often minting past the u64 maximum |
| 0xf | 15 | AuthorityTypeNotSupported | Account does not support specified authority type | SetAuthority was called with an authority type the account does not have |
| 0x10 | 16 | MintCannotFreeze | This token mint cannot freeze accounts | Freeze or thaw on a mint with no freeze authority |
| 0x11 | 17 | AccountFrozen | Account is frozen | The freeze authority froze this account. Only it can thaw the account |
| 0x12 | 18 | MintDecimalsMismatch | decimals different from the Mint decimals | A *Checked instruction passed the wrong decimals for the mint |
| 0x13 | 19 | NonNativeNotSupported | Instruction does not support non-native tokens | The instruction only works on wrapped SOL, such as SyncNative |
The three that ordinary users hit most are 0x1 (not enough tokens, often because the app and wallet disagree on decimals), 0xb (closing an account with dust left in it) and 0x11 (a frozen account). The closing cases are covered step by step in can't close a Solana token account, and frozen accounts in mint authority vs freeze authority.
What are the extra Token-2022 error codes?
Token-2022 adds 49 codes, 0x14 to 0x44 (20 to 68), for its extensions, on top of the 20 shared with SPL Token. They are listed in the Token-2022 error.rs as of November 2026. The newest entries at the bottom may only appear once the deployed program has been upgraded to include them.
| Hex | Dec | Name | What it means |
|---|---|---|---|
| 0x14 | 20 | ExtensionTypeMismatch | Extension type does not match existing extensions |
| 0x15 | 21 | ExtensionBaseMismatch | Extension is for a mint but used on an account, or the reverse |
| 0x16 | 22 | ExtensionAlreadyInitialized | Extension already initialized on this account |
| 0x17 | 23 | ConfidentialTransferAccountHasBalance | Cannot close: confidential balance is not zero |
| 0x18 | 24 | ConfidentialTransferAccountNotApproved | Account not approved for confidential transfers |
| 0x19 | 25 | ConfidentialTransferDepositsAndTransfersDisabled | Account not accepting deposits or transfers |
| 0x1a | 26 | ConfidentialTransferElGamalPubkeyMismatch | ElGamal public key mismatch |
| 0x1b | 27 | ConfidentialTransferBalanceMismatch | Confidential balance mismatch |
| 0x1c | 28 | MintHasSupply | Cannot close a mint with tokens in circulation; burn them first |
| 0x1d | 29 | NoAuthorityExists | No authority exists to perform this operation |
| 0x1e | 30 | TransferFeeExceedsMaximum | Transfer fee above the 10,000 basis point maximum |
| 0x1f | 31 | MintRequiredForTransfer | Use TransferChecked; plain Transfer is not allowed for this mint |
| 0x20 | 32 | FeeMismatch | Calculated transfer fee does not match the expected fee |
| 0x21 | 33 | FeeParametersMismatch | Zero-knowledge proof fee parameters do not match the mint |
| 0x22 | 34 | ImmutableOwner | The account's owner cannot be changed |
| 0x23 | 35 | AccountHasWithheldTransferFees | Cannot close: withheld transfer fees remain; harvest them to the mint first |
| 0x24 | 36 | NoMemo | Recipient requires a memo in the previous instruction |
| 0x25 | 37 | NonTransferable | The mint is non-transferable (soulbound) |
| 0x26 | 38 | NonTransferableNeedsImmutableOwnership | Non-transferable tokens need an immutable-owner account |
| 0x27 | 39 | MaximumPendingBalanceCreditCounterExceeded | Too many confidential deposits or transfers pending |
| 0x28 | 40 | MaximumDepositAmountExceeded | Confidential deposit above the maximum |
| 0x29 | 41 | CpiGuardSettingsLocked | CPI Guard cannot be toggled inside a CPI |
| 0x2a | 42 | CpiGuardTransferBlocked | CPI Guard blocked a program transfer without a delegate |
| 0x2b | 43 | CpiGuardBurnBlocked | CPI Guard blocked a program burn without a delegate |
| 0x2c | 44 | CpiGuardCloseAccountBlocked | CPI Guard blocked a close that does not return SOL to the owner |
| 0x2d | 45 | CpiGuardApproveBlocked | CPI Guard blocked a delegate approval |
| 0x2e | 46 | CpiGuardSetAuthorityBlocked | CPI Guard blocked adding or replacing an authority |
| 0x2f | 47 | CpiGuardOwnerChangeBlocked | Ownership cannot change while CPI Guard is on |
| 0x30 | 48 | ExtensionNotFound | Extension not found in account data |
| 0x31 | 49 | NonConfidentialTransfersDisabled | Only confidential transfers are allowed |
| 0x32 | 50 | ConfidentialTransferFeeAccountHasWithheldFee | Cannot close: confidential withheld fee is not zero |
| 0x33 | 51 | InvalidExtensionCombination | Invalid combination of extensions |
| 0x34 | 52 | InvalidLengthForAlloc | Reallocation with overwrite must keep the same length |
| 0x35 | 53 | AccountDecryption | Failed to decrypt a confidential account |
| 0x36 | 54 | ProofGeneration | Failed to generate a proof |
| 0x37 | 55 | InvalidProofInstructionOffset | Invalid proof instruction offset |
| 0x38 | 56 | HarvestToMintDisabled | Harvesting withheld fees to the mint is disabled |
| 0x39 | 57 | SplitProofContextStateAccountsNotSupported | Split proof context accounts not supported here |
| 0x3a | 58 | NotEnoughProofContextStateAccounts | Not enough proof context accounts provided |
| 0x3b | 59 | MalformedCiphertext | Ciphertext is malformed |
| 0x3c | 60 | CiphertextArithmeticFailed | Ciphertext arithmetic failed |
| 0x3d | 61 | PedersenCommitmentMismatch | Pedersen commitment mismatch |
| 0x3e | 62 | RangeProofLengthMismatch | Range proof length mismatch |
| 0x3f | 63 | IllegalBitLength | Illegal transfer amount bit length |
| 0x40 | 64 | FeeCalculation | Fee calculation failed |
| 0x41 | 65 | IllegalMintBurnConversion | Withdraw or deposit not allowed for confidential mint-burn |
| 0x42 | 66 | InvalidScale | Invalid scale for the scaled UI amount extension |
| 0x43 | 67 | MintPaused | Transfers, minting and burning are paused on this mint |
| 0x44 | 68 | PendingBalanceNonZero | Key rotation attempted with a pending balance |
For traders the relevant ones are 0x23 (harvest withheld fees before closing, explained in how to set and claim Token-2022 transfer fees), 0x1f (an app used the wrong transfer instruction), 0x25 (the token cannot be moved at all) and 0x43 (the issuer paused the mint). What those extensions are for is covered in Token-2022 explained for traders.
What are the Associated Token Account program errors?
The Associated Token Account program (ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL) defines only one custom error: 0x0, InvalidOwner, "Associated token account owner does not match address derivation". Everything else it returns is a standard runtime error, which shows up as a name rather than a number. From the ATA processor source:
| Error shown | Cause | Fix |
|---|---|---|
| custom program error: 0x0 (InvalidOwner) | An existing account at that address is owned by a different wallet | Pass the correct wallet and mint |
| IllegalOwner ("Provided owner is not allowed") | Plain Create was called but the account already exists | Use CreateIdempotent, or skip the create step |
| InvalidSeeds ("Provided seeds do not result in a valid address") | The address passed is not the derived ATA for that wallet, mint and token program | Derive the address with the right token program (SPL Token or Token-2022) |
| InvalidAccountData | Idempotent create found an account for a different mint | Check the mint |
Note that a 0x0 from the ATA program and a 0x0 from the System program are different errors, which is the whole reason to check the program first.
What do the System program error codes mean?
The System program (11111111111111111111111111111111) has nine custom errors, 0x0 to 0x8, from the SystemError enum in the Solana SDK source. The log messages come from the Agave system processor.
| Hex | Dec | Name | Log text you may see | Meaning and fix |
|---|---|---|---|---|
| 0x0 | 0 | AccountAlreadyInUse | Create Account: account ... already in use | The address being created already exists. Often harmless; skip the create |
| 0x1 | 1 | ResultWithNegativeLamports | Transfer: insufficient lamports X, need Y | The sender lacks the SOL being transferred or deposited. Add SOL or send less |
| 0x2 | 2 | InvalidProgramId | Cannot assign the account to this program | |
| 0x3 | 3 | InvalidAccountDataLength | The requested account size is not allowed (above the 10 MiB limit) | |
| 0x4 | 4 | MaxSeedLengthExceeded | A seed longer than 32 bytes was used for a derived address | |
| 0x5 | 5 | AddressWithSeedMismatch | The address does not match the base, seed and owner provided | |
| 0x6 | 6 | NonceNoRecentBlockhashes | Advancing a durable nonce needs the RecentBlockhashes sysvar | |
| 0x7 | 7 | NonceBlockhashNotExpired | The stored nonce is still the current blockhash, so it cannot be advanced yet; wait and retry | |
| 0x8 | 8 | NonceUnexpectedBlockhashValue | The transaction's nonce does not match the stored nonce |
The System program's 0x1 is the classic "not enough SOL" during a transaction. The "Transfer: insufficient lamports" line in the logs states both numbers in lamports, so you can see exactly how short you were. One SOL is 1,000,000,000 lamports.
What are the common Anchor framework error codes?
Anchor errors split into two groups: framework errors below 6000, which mean the same thing in every Anchor program, and custom errors from 6000 (0x1770) up, which each program defines itself. The framework ranges, from the ErrorCode enum in Anchor's lang/error source (the repository formerly at coral-xyz/anchor), are 100+ for instruction errors, 1000+ for IDL errors, 2000+ for account constraints, 2500+ for require! checks, 3000+ for account errors and 4100+ for miscellaneous errors. The ones you are most likely to see:
| Hex | Dec | Name | What it means |
|---|---|---|---|
| 0x65 | 101 | InstructionFallbackNotFound | The instruction discriminator matched nothing; often an outdated client or wrong program |
| 0x66 | 102 | InstructionDidNotDeserialize | Instruction arguments could not be decoded; client and program versions disagree |
| 0x7d0 | 2000 | ConstraintMut | An account marked mut was passed as read-only |
| 0x7d1 | 2001 | ConstraintHasOne | A has_one relationship between accounts did not match |
| 0x7d2 | 2002 | ConstraintSigner | An account that must sign did not |
| 0x7d3 | 2003 | ConstraintRaw | A custom constraint = ... expression was false |
| 0x7d4 | 2004 | ConstraintOwner | An account is not owned by the expected program |
| 0x7d6 | 2006 | ConstraintSeeds | A PDA does not match its expected seeds |
| 0x7dc | 2012 | ConstraintAddress | An account is not at the required address |
| 0x7de | 2014 | ConstraintTokenMint | A token account is for the wrong mint |
| 0x7df | 2015 | ConstraintTokenOwner | A token account has the wrong owner |
| 0x7f8 | 2040 | ConstraintDuplicateMutableAccount | The same account was passed twice as mutable |
| 0x9c4 | 2500 | RequireViolated | A require! check in the program failed |
| 0xbb9 | 3001 | AccountDiscriminatorNotFound | The account is too small to hold a discriminator, often not created yet |
| 0xbba | 3002 | AccountDiscriminatorMismatch | The account is of a different type than expected |
| 0xbbb | 3003 | AccountDidNotDeserialize | The account data could not be decoded, often after a program upgrade |
| 0xbbd | 3005 | AccountNotEnoughKeys | Too few accounts passed to the instruction |
| 0xbbe | 3006 | AccountNotMutable | The account is not writable |
| 0xbbf | 3007 | AccountOwnedByWrongProgram | The account is owned by a different program than expected |
| 0xbc0 | 3008 | InvalidProgramId | The wrong program was passed |
| 0xbc2 | 3010 | AccountNotSigner | The account did not sign |
| 0xbc3 | 3011 | AccountNotSystemOwned | The account is not owned by the System program |
| 0xbc4 | 3012 | AccountNotInitialized | An account the instruction expected to exist has not been created |
| 0x1004 | 4100 | DeclaredProgramIdMismatch | The program's declared id does not match where it is deployed |
| 0x1770 | 6000 | (custom) | First error defined by the program itself |
As a user, the Anchor framework errors usually mean the app built the transaction wrong, not that you did something wrong. 3012 is the exception you can sometimes act on: it often means an account you were supposed to create first, such as a token account or a user profile in that app, does not exist yet.
Why does 0x1771 mean different things in different programs?
0x1771 means different things because Anchor numbers each program's custom errors from 6000 in the order its developers declared them, so 6001 is simply the second error in that program's list. Anchor even allows a different starting offset per program. I read the error lists below from the Anchor IDL stored on chain for Jupiter v6, pump.fun and PumpSwap, and from the GitHub source for Raydium, whose CPMM and CLMM programs do not publish an on-chain IDL:
| Code | Jupiter v6 | pump.fun | PumpSwap | Raydium CPMM | Raydium CLMM |
|---|---|---|---|---|---|
| 6000 (0x1770) | EmptyRoute | NotAuthorized | FeeBasisPointsExceedsMaximum | NotApproved | NotApproved |
| 6001 (0x1771) | SlippageToleranceExceeded | AlreadyInitialized | ZeroBaseAmount | InvalidOwner | InvalidUpdateConfigFlag |
| 6002 (0x1772) | InvalidCalculation | TooMuchSolRequired | ZeroQuoteAmount | EmptySupply | AccountLack |
| 6003 (0x1773) | MissingPlatformFeeAccount | TooLittleSolReceived | TooLittlePoolTokenLiquidity | InvalidInput | ClosePositionErr |
| 6004 (0x1774) | InvalidSlippage | MintDoesNotMatchBondingCurve | ExceededSlippage | IncorrectLpMint | InvalidTickIndex |
| 6005 (0x1775) | NotEnoughPercent | BondingCurveComplete | InvalidAdmin | ExceededSlippage | TickInvalidOrder |
So the slippage error has a different number in each program. This is the lookup that matters most for traders:
| Program | Program ID | Slippage error |
|---|---|---|
| Jupiter v6 aggregator | JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4 | 6001 (0x1771) SlippageToleranceExceeded; 6017 (0x1781) ExactOutAmountNotMatched for exact-out swaps |
| pump.fun bonding curve | 6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P | 6002 (0x1772) TooMuchSolRequired on buys; 6003 (0x1773) TooLittleSolReceived on sells |
| PumpSwap AMM | pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA | 6004 (0x1774) ExceededSlippage |
| Raydium AMM v4 | 675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8 | 30 (0x1e) ExceededSlippage (native program, not Anchor) |
| Raydium CPMM | CPMMoo8L3F4NbTegBCKVNunggL7H1ZpdTHKxQB5qKP1C | 6005 (0x1775) ExceededSlippage |
| Raydium CLMM | CAMMCzo5YL8w4VFF8KVHrK22GGUsp5VTaW7grrKgrWqK | 6017 (0x1781) PriceSlippageCheck, 6018 (0x1782) TooLittleOutputReceived, 6019 (0x1783) TooMuchInputPaid |
Sources: the on-chain IDLs of the first three programs as of November 4, 2026, the Jupiter CPI IDL, and Raydium's AMM v4, CPMM and CLMM error files. Jupiter's own common errors page adds two codes worth knowing: 6024 (0x1788) InsufficientFunds, for swap amount, fees or rent, and 6025 (0x1789) InvalidTokenAccount.
The practical lesson: when a Jupiter swap fails with 0x1771, the error came from Jupiter. When it fails with 0x1e, Jupiter routed through Raydium AMM v4 and the pool's own slippage check stopped it, and the first "failed" log line names Raydium, not Jupiter. Either way the fix is the same: a fresh quote, a smaller size or a wider slippage setting.
What do runtime transaction errors like BlockhashNotFound mean?
Runtime transaction errors are produced by the validator, not by a program, so they appear as names with no hex code. They come from the TransactionError enum in the Solana SDK source. Most of them reject the transaction before it runs, which means no fee is charged; the cost rules are explained in Solana transaction fees explained.
| Error name | Message text | Meaning and fix |
|---|---|---|
| BlockhashNotFound | Blockhash not found | The blockhash expired or the RPC node has not seen it. Rebuild and sign again |
| AccountNotFound | Attempt to debit an account but found no record of a prior credit. | The fee payer does not exist, meaning it has zero SOL. Fund it with native SOL |
| InsufficientFundsForFee | Insufficient funds for fee | The fee payer cannot cover the fee. Add SOL, or unwrap wSOL |
| InsufficientFundsForRent | Transaction results in an account (N) with insufficient funds for rent | Account number N would end up with SOL but below its rent-exempt minimum. Leave more SOL in it |
| InstructionError | Error processing Instruction N: ... | Instruction N (zero-based) failed. The detail is a runtime error or a custom program error |
| AlreadyProcessed | This transaction has already been processed | The same signed transaction landed already. Check its status before resending |
| AccountInUse | Account in use | Another transaction in the same batch holds a lock on the account. Retry |
| DuplicateInstruction | Transaction contains a duplicate instruction (N) that is not allowed | Usually two Compute Budget instructions of the same kind |
| WouldExceedMaxBlockCostLimit | Transaction would exceed max Block Cost Limit | The block was full. Retry, possibly with a higher priority fee |
| ProgramAccountNotFound | Attempt to load a program that does not exist | The transaction calls a program address that has no program |
| MaxLoadedAccountsDataSizeExceeded | Transaction exceeded max loaded accounts data size cap | The accounts the transaction loads are too large in total |
InsufficientFundsForRent is the one to remember for small wallets: Solana will not leave an account holding SOL below its rent-exempt minimum. A new token account needs 0.00148844 SOL, which is the usual reason a first-time buy fails on a nearly empty wallet. The rent calculator gives the minimum for any account size, and what is Solana rent explains why it exists.
What do instruction errors like ProgramFailedToComplete mean?
Instruction errors are the named, non-custom failures inside InstructionError, such as ProgramFailedToComplete or InsufficientFunds. They come from the runtime rather than a program's own list, from the InstructionError enum:
| Name | Message text | Usual cause |
|---|---|---|
| ProgramFailedToComplete | Program failed to complete | The program aborted. If the log says "exceeded CUs meter at BPF instruction", it ran out of compute units |
| ComputationalBudgetExceeded | Computational budget exceeded | Compute units ran out while the runtime charged for a call or syscall |
| InsufficientFunds | insufficient funds for instruction | An account lacked the lamports the instruction needed |
| MissingRequiredSignature | missing required signature for instruction | A required signer did not sign |
| AccountNotRentExempt | An account does not have enough lamports to be rent-exempt | The account was underfunded |
| InvalidAccountData | invalid account data for instruction | An account held data the program did not expect, often the wrong account |
| AccountAlreadyInitialized | instruction requires an uninitialized account | The account already exists |
| UninitializedAccount | instruction requires an initialized account | The account has not been created |
| IncorrectProgramId | incorrect program id for instruction | Wrong program for that account, often SPL Token versus Token-2022 |
| IllegalOwner | Provided owner is not allowed | The account is owned by an unexpected program |
| InvalidSeeds | Provided seeds do not result in a valid address | A derived address does not match its seeds |
| Custom(N) | custom program error: 0x... | The program's own error number N; look it up in that program's list |
The compute case is worth spelling out, because it is the one people search for. When a program runs out of compute units, the log shows Program <address> failed: exceeded CUs meter at BPF instruction and the instruction error is ProgramFailedToComplete, as the Agave invoke context shows; ComputationalBudgetExceeded appears when the meter runs out during a runtime-charged operation. The default limit is 200,000 compute units per instruction and the maximum is 1,400,000 per transaction, per Agave's compute budget constants. The fix is a higher compute unit limit, set by the app; the priority fee tracker shows the price side, and how much priority fee to pay explains why the limit you request matters for cost.
Bottom line
A Solana error code is only meaningful next to the program that raised it: find the first Program ... failed line in the logs, convert the hex code to decimal, and look it up in that program's list. In the core programs, 0x1 is "not enough SOL" (System) or "not enough tokens" (SPL Token and Token-2022), 0xb and 0x23 block account closes, and 0x11 means frozen. Anchor's 2000 to 4100 range means the same in every Anchor program, while 6000 and up are program-specific, which is why 0x1771 is Jupiter slippage but something else entirely in pump.fun or Raydium. Runtime errors such as BlockhashNotFound and AccountNotFound are names, not numbers, and usually cost nothing. To skip the manual lookup, paste the signature into the free Transaction Decoder, and for the causes behind the codes, see why Solana transactions fail.
Questions & answers
What does custom program error 0x1 mean on Solana?
It is error number 1 of whichever program failed. In the System program it is ResultWithNegativeLamports, meaning the sender lacked the SOL being transferred. In the SPL Token and Token-2022 programs it is InsufficientFunds, meaning the token account held less than the amount sent. In any other program 0x1 means something else, so check the 'Program ... failed' line in the logs to see which program raised it.
What does custom program error 0x1771 mean?
0x1771 is hexadecimal for 6001, the second custom error defined by an Anchor program. In Jupiter v6 it is SlippageToleranceExceeded, so the swap would have returned less than your minimum. In pump.fun 6001 is AlreadyInitialized and in Raydium CPMM it is InvalidOwner, so the meaning depends entirely on which program failed. For a Jupiter swap, retry with a fresh quote or wider slippage.
How do I convert a Solana error code from hex to decimal?
Drop the 0x and read the rest as base 16. In a browser console, parseInt('1771', 16) returns 6001; in Python, int('1771', 16) does the same; in a terminal, printf '%d' 0x1771 works. The transaction's JSON error already shows the decimal form, for example Custom 6001, while the program logs show the hex form 0x1771.
What does 'Attempt to debit an account but found no record of a prior credit' mean?
It is the AccountNotFound transaction error. The fee payer account does not exist on chain, which means the wallet has never held SOL or has a balance of zero. The transaction is rejected before it runs and costs nothing. Send a small amount of native SOL to the wallet first; wrapped SOL in a token account does not count.
What is the difference between Anchor error 3012 and custom error 6000?
3012 (0xbc4) is AccountNotInitialized, one of Anchor's built-in framework errors, and it means the same thing in every Anchor program: an account the instruction expected to exist has not been created. 6000 (0x1770) and above are errors the program's developers defined themselves, so 6000 in Jupiter, pump.fun and Raydium are three different errors that you look up in each program's IDL.
Why does a failed Solana transaction show the same error twice in the logs?
When one program calls another and the inner call fails, the caller cannot catch the error, so it fails too with the same code. The logs then show 'Program X failed' for the inner program first and again for each program above it. The first failed line, the deepest one, names the program that actually raised the error and whose error list you need.