> ## 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.

# Error handling

> Current SDK error types, stale-root retries, and relay/on-chain diagnostics

## SDK error surfaces

`@cloak.dev/sdk` exposes two main layers:

1. `CloakError` (runtime SDK operations)
2. `parseError` / `parseTransactionError` (user-facing normalization)

## `CloakError`

```typescript theme={null}
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:

<CodeGroup>
  ```typescript Keypair bytes theme={null}
  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
  }
  }

  ```

  ```typescript Wallet adapter theme={null}
  import { isRootNotFoundError, RootNotFoundError } from "@cloak.dev/sdk";

  try {
    await partialWithdraw(inputUtxos, recipient, 10_000_000n, {
      connection,
      programId,
      relayUrl,
      walletPublicKey: publicKey!,
      signMessage: signMessage!,
    });
  } catch (error) {
    if (error instanceof RootNotFoundError || isRootNotFoundError(error)) {
      // Rebuild with fresh commitments/root and retry
    }
  }
  ```
</CodeGroup>

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:

```typescript theme={null}
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

<CodeGroup>
  ```typescript Keypair bytes theme={null}
  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
  }

  ```

  ```typescript Wallet adapter theme={null}
  import { parseError, type UserFriendlyError } from "@cloak.dev/sdk";

  try {
    await swapWithChange(inputUtxos, amountLamports, outputMint, recipientAta, minOutput, {
      connection,
      programId,
      relayUrl,
      walletPublicKey: publicKey!,
      signMessage: signMessage!,
    });
  } catch (error) {
    const parsed: UserFriendlyError = parseError(error);
    // parsed.category / parsed.recoverable
  }
  ```
</CodeGroup>

## 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

```typescript theme={null}
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).
