Waldrop SDK · API Reference

Errors

Every SDK error extends WaldropError. Narrow on these classes in your catch blocks — string-matching error messages is brittle and breaks on upstream changes.

Hierarchy

WaldropErrorbase
├── BlobStoreNotFoundErrorno BlobStore owned by address
├── BlobNotFoundErroraggregator returned 404
├── AggregatorErrornon-2xx from aggregator (non-404)
├── DecryptionErrorSEAL decrypt failed
├── SealNotInstalledError@mysten/seal peer dep missing
└── RegistrationErrorbytes on Walrus, register tx failed
    └── InsufficientGasErrorwallet out of SUI for gas

Sample catch

import {
  WaldropError,
  RegistrationError,
  InsufficientGasError,
  BlobStoreNotFoundError,
} from "@waldrop/sdk";

try {
  await client.blob.upload({ … });
} catch (err) {
  if (err instanceof InsufficientGasError) {
    // wallet needs more SUI — show faucet prompt
    showFaucetPrompt(err.address, err.requiredMist);
  } else if (err instanceof RegistrationError) {
    // bytes on Walrus already — retry register only
    await client.blob.registerOnly({
      checkpoint: err.checkpoint, /* … */
    });
  } else if (err instanceof BlobStoreNotFoundError) {
    // user hasn't stored anything yet
  } else if (err instanceof WaldropError) {
    console.error("SDK error:", err.message, err.cause);
  } else {
    throw err;
  }
}

WaldropError

class WaldropError extends Error {
  cause?: unknown;     // underlying error (Node 16.9+ standard)
}

Base class. All SDK errors set err.name to their class name so log formatters can pick them out without instanceof checks.

BlobStoreNotFoundError

class BlobStoreNotFoundError extends WaldropError {
  readonly owner: string;   // the queried address
}

Thrown by client.blob.list, .getStore, and .listViewers when the queried address has never created a BlobStore. Treat as an empty state, not a failure.

BlobNotFoundError

class BlobNotFoundError extends WaldropError {
  readonly blobId: string;
}

The aggregator returned 404 for client.blob.fetch. The blob id might be malformed, or the blob's storage reservation expired and was garbage-collected.

AggregatorError

class AggregatorError extends WaldropError {
  readonly status: number;
  readonly bodyPreview: string;   // first 200 chars of response body
}

Non-404 non-2xx from the aggregator (5xx, network, malformed response).

DecryptionError

class DecryptionError extends WaldropError {}

client.crypto.decrypt failed. Usually one of: wrong blobStoreId, the caller isn't an allowlisted viewer, or the bytes aren't valid SEAL ciphertext.

SealNotInstalledError

class SealNotInstalledError extends WaldropError {}

The optional @mysten/seal peer dep isn't installed but you called client.crypto.encrypt or .decrypt. Install it:

npm install @mysten/seal

RegistrationError

class RegistrationError extends WaldropError {
  readonly checkpoint: UploadCheckpoint;   // pass to registerOnly to retry
}

The publisher PUT succeeded — your bytes are on Walrus, storage tokens are spent — but the on-chain register_blob transaction failed. The checkpoint field carries everything client.blob.registerOnly needs to finish without re-uploading.

interface UploadCheckpoint {
  blobId: string;
  sizeBytes: number;
  contentHash: Uint8Array;
  fileName: string;
  contentType: string;
  encrypted: boolean;
  sealMarker?: string;
}

InsufficientGasError

class InsufficientGasError extends RegistrationError {
  readonly requiredMist: number | null;   // gas budget the tx wanted
  readonly address: string | null;        // wallet that needs topping up
}

A specialization of RegistrationError for the most common cause: wallet doesn't have enough SUI to pay gas. Catch it explicitly to render a "top up your wallet" UI before falling through to the generic registration-failed handler.

Both carry .checkpoint

InsufficientGasError inherits .checkpoint from RegistrationError — the resume path is identical, the typed subclass exists purely for UX.

Edit this page on GitHub ↗
Waldrop · 2026cryptokarigar