Skip to content
Launch App >

Error codes returned by the zklsol on-chain program.

CodeNameDescription
6000UnauthorizedSigner is not authorized for this operation
6001InvalidAmountAmount is invalid (zero or negative)
6002InvalidDepositSizeAmount doesn’t match allowed deposit sizes
6003MathOverflowArithmetic overflow occurred
6004AccountNotInitializedRequired account not initialized
CodeNameDescription
6010MerkleTreeFullTree has reached maximum capacity
6011InvalidMerkleDepthDepth must be 32
6012InvalidMerkleRootRoot doesn’t match on-chain state
6013MerkleTreePausedTree is temporarily paused
6014MerkleTreeClosedTree is permanently closed
CodeNameDescription
6020InvalidProofZK proof verification failed
6021InvalidCommitmentCommitment format invalid
6022CommitmentNotFoundCommitment doesn’t exist in tree
6023ProofLengthMismatchProof is wrong length (expected 256 bytes)
CodeNameDescription
6030NullifierAlreadySpentThis deposit was already withdrawn
6031InvalidNullifierHashNullifier hash format invalid
CodeNameDescription
6040CannotRevertDeposit cannot be reverted
6041AlreadyIndexedDeposit was indexed, use normal withdraw
6042NotDepositorOnly original depositor can revert
6043RevertWindowExpiredRevert time window has passed
CodeNameDescription
6050AffiliateAlreadyExistsAffiliate code already registered
6051AffiliateNotFoundAffiliate account doesn’t exist
6052InvalidFeeShareFee share must be 0-10000 bps
6053NoEarningsToWithdrawNo pending earnings available
CodeNameDescription
6060SwapFailedJupiter swap execution failed
6061SlippageExceededOutput less than minimum
6062InvalidSwapRouteSwap route data invalid
6063SwapBufferNotFoundSwap buffer account missing
CodeNameDescription
6070LutNotFoundAddress Lookup Table doesn’t exist
6071LutNotActiveLUT is deactivated
6072LutFullLUT has max addresses
6073CooldownNotCompleteMust wait before closing LUT
import { AnchorError } from '@coral-xyz/anchor';
try {
await program.methods.withdraw(/* ... */).rpc();
} catch (err) {
if (err instanceof AnchorError) {
switch (err.error.errorCode.code) {
case 'NullifierAlreadySpent':
console.log('Already withdrawn this deposit');
break;
case 'InvalidProof':
console.log('Proof verification failed - regenerate proof');
break;
case 'InvalidMerkleRoot':
console.log('Merkle root changed - refetch and retry');
break;
default:
console.log('Program error:', err.error.errorMessage);
}
} else {
console.log('Transaction error:', err);
}
}

Cause: Attempting to withdraw a deposit that was already withdrawn.

Solution:

  1. Check your local records - deposit may be marked spent
  2. If records are lost, the funds are already withdrawn

Cause: The ZK proof failed verification.

Solutions:

  1. Ensure nullifier and secret match the original deposit
  2. Verify Merkle proof path is current
  3. Check that all inputs are correctly formatted
  4. Regenerate proof with fresh data

Cause: The Merkle root in your proof is outdated.

Solution:

  1. Fetch the current Merkle root
  2. Regenerate the proof with the new root
  3. Retry within a reasonable time window

Cause: The tree has 2³² deposits (extremely rare).

Solution:

  1. Use a different deposit size (different tree)
  2. Wait for a new tree to be created

Cause: Deposit was indexed or nullifier was spent.

Solutions:

  1. If indexed: Use normal withdrawal flow
  2. If spent: Funds were already withdrawn
  1. Log the full error:

    console.log(JSON.stringify(err, null, 2));
  2. Check transaction logs:

    const tx = await connection.getTransaction(signature);
    console.log(tx.meta.logMessages);
  3. Verify account states:

    const nullifierPda = getNullifierHashPda(mint, depth, nullifierHash);
    const exists = await connection.getAccountInfo(nullifierPda);
    console.log('Nullifier spent:', exists !== null);