Documentation Index Fetch the complete documentation index at: https://docs.cloak.ag/llms.txt
Use this file to discover all available pages before exploring further.
SDK error surfaces
@cloak.dev/sdk exposes two main layers:
CloakError (runtime SDK operations)
parseError / parseTransactionError (user-facing normalization)
CloakError
import { CloakError } from "@cloak.dev/sdk" ;
// category values:
// "network" | "indexer" | "prover" | "relay" | "validation" | "wallet" | "environment"
Most app flows should treat retryable === true as backoff-eligible.
Stale Merkle root (0x1001)
Use helpers for RootNotFound detection:
Keypair bytes
Wallet adapter
import { isRootNotFoundError , RootNotFoundError } from "@cloak.dev/sdk" ;
try {
await sdk . withdraw ( connection , note , recipient );
} catch ( error ) {
if ( error instanceof RootNotFoundError || isRootNotFoundError ( error )) {
// Refresh proof inputs and retry flow
}
}
SDK note and UTXO flows already include retry loops; this usually appears only after retries are exhausted.
On-chain error message mapping
ShieldPoolErrors maps known custom program codes:
import { ShieldPoolErrors } from "@cloak.dev/sdk" ;
console . log ( ShieldPoolErrors [ 0x1001 ]); // Root not found in the roots ring
console . log ( ShieldPoolErrors [ 0x1076 ]); // Proof verification failed
User-facing normalization
Keypair bytes
Wallet adapter
import { parseError , type UserFriendlyError } from "@cloak.dev/sdk" ;
try {
await sdk . swap ( connection , note , recipient , swapOptions );
} catch ( error ) {
const parsed : UserFriendlyError = parseError ( error );
// parsed.category: wallet | network | validation | service | transaction | unknown
// parsed.recoverable: boolean
}
Practical retry strategy
Retry network and service failures with exponential backoff.
Avoid retrying deterministic validation failures.
On stale-root errors, rebuild proof data before retrying.
UTXO stale-root retry template
import { fullWithdraw , isRootNotFoundError } from "@cloak.dev/sdk" ;
let result : Awaited < ReturnType < typeof fullWithdraw >> | undefined ;
let cachedMerkleTree = initialMerkleTree ;
for ( let attempt = 1 ; attempt <= 3 ; attempt += 1 ) {
try {
result = await fullWithdraw ( inputUtxos , recipientWallet , {
connection ,
programId ,
relayUrl ,
walletPublicKey ,
signMessage ,
cachedMerkleTree ,
});
break ;
} catch ( error ) {
if ( ! isRootNotFoundError ( error ) || attempt === 3 ) throw error ;
await new Promise (( resolve ) => setTimeout ( resolve , 1_500 * attempt ));
// refresh proof inputs before retrying (new root + updated tree)
cachedMerkleTree = undefined ;
}
}
if ( ! result ) throw new Error ( "withdraw did not complete" );
Security logging rule
Never log full notes/UTXOs with secrets. Log only non-sensitive identifiers (commitment prefix, leaf index, request ID, and tx signature when needed for support).