Skip to main content

SDK error surfaces

@cloak.ag/sdk exposes two main layers:
  1. CloakError (runtime SDK operations)
  2. parseError / parseTransactionError (user-facing normalization)

CloakError

import { CloakError } from "@cloak.ag/sdk";

// category values in core/types.ts:
// "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:
import { isRootNotFoundError, RootNotFoundError } from "@cloak.ag/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.ag/sdk";

console.log(ShieldPoolErrors[0x1001]); // Root not found in the roots ring
console.log(ShieldPoolErrors[0x1076]); // Proof verification failed

User-facing normalization

import { parseError, type UserFriendlyError } from "@cloak.ag/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.

Security logging rule

Never log full notes/UTXOs with secrets. Log only non-sensitive identifiers (commitment prefix, leaf index, request ID).