@zethub/bridge
Recovery

Error handling

Typed error codes, stable messages, and how the SDK signals failures.

Every failure the SDK raises is a BridgeError with a stable code on the ErrorCode map. Branch on the code, not on the message text.

The shape

import { BridgeError, ErrorCode, ErrorMessage } from "@zethub/bridge";

try {
  const tx = await sdk.bridge.rawTxBuilder.send({ ... });
} catch (err) {
  if (err instanceof BridgeError) {
    console.log(err.code);     // a value from ErrorCode
    console.log(err.message);  // human readable copy from ErrorMessage
    console.log(err.cause);    // underlying error, when there was one
  }
}

When errors are thrown

The SDK returns unsigned transactions. It does not run flows, so it does not surface flow errors. Every method that touches the network can throw a BridgeError if:

  • the requested route is invalid or misconfigured,
  • the network returns a bad response,
  • the input fails validation (bad amount, bad address, etc).

Signing and broadcasting errors come from your wallet library, not the SDK. Use BridgeError.from(err) to normalise them.

Common codes

CodeWhen it happens
MISSING_SOURCEThe passed NetworkId is not registered in the current environment.
MISSING_EVM_CHAIN_IDThe EVM network in the config is missing its chain id. Should not happen with the built in networks.
MISSING_FORWARDERA Stellar destination is missing its CctpForwarder address in the network config.
MISSING_TRUSTLINEThe Stellar recipient has no trustline for the asset.
UNSUPPORTED_ASSETThe requested asset is not on the given network.
UNSUPPORTED_ROUTENeither chain family has a connector registered.
MISMATCHED_ENVIRONMENTSThe source and destination tokens live on different environments.
SAME_NETWORKThe source and destination are the same network.
ATTESTATION_TIMEOUTIris did not attest before the timeout. Fetch again later.
RPC_ERROREvery configured RPC endpoint failed.
RPC_TIMEOUTAn RPC call timed out.
WALLET_SIGN_REJECTEDNormalised from a wallet library's user rejected error.
WRONG_NETWORKNormalised from a wallet library's wrong chain error.
AMOUNT_EXCEEDS_BALANCENormalised from a wallet library's insufficient funds error.

Classify a wallet error

BridgeError.from(err, fallback?) sniffs a unknown value and returns a BridgeError with the best matching code. If nothing matches, it returns one with the fallback (default UNKNOWN).

try {
  await wallet.sendTransaction({ ... });
} catch (err) {
  const known = BridgeError.from(err);
  if (known.code === "WALLET_SIGN_REJECTED") {
    // user cancelled, do not retry
    return;
  }
  throw known;
}

The classifier catches common phrasings:

  • user rejected, user denied, action_rejectedWALLET_SIGN_REJECTED
  • insufficient fundsAMOUNT_EXCEEDS_BALANCE
  • wrong network, chain mismatchWRONG_NETWORK

Messages are constants

Every message lives in an exported map keyed by code, so you can translate or replace them.

import { ErrorMessage } from "@zethub/bridge";

ErrorMessage.MISSING_TRUSTLINE;
// "The Stellar recipient has no trustline for this asset. Establish the trustline before bridging."

Override in bulk when localising:

const spanish: typeof ErrorMessage = {
  ...ErrorMessage,
  MISSING_TRUSTLINE: "El destinatario no tiene línea de confianza para USDC.",
  // ...
};

See the full error code reference for every code and its default message.

On this page