Skip to main content
Version: 1.x

Errors and Recovery

At app boundaries, classify raw wallet or SDK failures and show only UI-safe copy:

import { NitroliteClient, getUserFacingMessage } from '@yellow-org/sdk-compat';

try {
await client.deposit(tokenAddress, 11_000_000n);
} catch (err) {
const typed = NitroliteClient.classifyError(err);
showToast(getUserFacingMessage(typed));
throw typed;
}

Error Catalogue

Error classCodeTriggerRecovery
CompatErrorvariesBase compat failureLog error.code; show getUserFacingMessage(error)
AllowanceErrorALLOWANCE_INSUFFICIENTChannelHub needs ERC-20 allowanceApprove, then retry
UserRejectedErrorUSER_REJECTEDWallet rejected a signature or transactionShow retry UI; do not auto-loop prompts
InsufficientFundsErrorINSUFFICIENT_FUNDSNot enough gas or token balanceShow funding guidance
NotInitializedErrorNOT_INITIALIZEDWallet/client is disconnectedReconnect and recreate the client
OngoingStateTransitionErrorONGOING_STATE_TRANSITIONPrevious transition still finalizingPoll status, then retry

Allowance

Compat token helpers use token addresses and raw token units:

import { AllowanceError, NitroliteClient, getUserFacingMessage } from '@yellow-org/sdk-compat';

try {
await client.deposit(tokenAddress, 11_000_000n);
} catch (err) {
const typed = NitroliteClient.classifyError(err);
showToast(getUserFacingMessage(typed));

if (typed instanceof AllowanceError) {
await client.approveTokens(tokenAddress, 11_000_000n);
await client.deposit(tokenAddress, 11_000_000n);
}
}

When you fall through to native v1, use client.innerClient.approveToken(chainId, asset, amount) with Decimal:

import Decimal from 'decimal.js';
import { getUserFacingMessage } from '@yellow-org/sdk-compat';

try {
await client.innerClient.checkpoint('usdc');
} catch (err) {
showToast(getUserFacingMessage(err));
// Native v1 approveToken expects a bigint chain ID.
await client.innerClient.approveToken(11155111n, 'usdc', new Decimal(11));
await client.innerClient.checkpoint('usdc');
}

Prompt and Reconnect

For UserRejectedError, show getUserFacingMessage(error) and expose an explicit retry button. Do not auto-loop wallet prompts. For NotInitializedError, reconnect the wallet and recreate NitroliteClient before retrying.

Ongoing Transition

Use EventPoller to wait for channel status to settle before enabling another write:

import {
EventPoller,
OngoingStateTransitionError,
NitroliteClient,
RPCChannelStatus,
getUserFacingMessage,
} from '@yellow-org/sdk-compat';

try {
await client.deposit(tokenAddress, 11_000_000n);
} catch (err) {
const typed = NitroliteClient.classifyError(err);
showToast(getUserFacingMessage(typed));

if (typed instanceof OngoingStateTransitionError) {
const poller = new EventPoller(client, {
onChannelUpdate: (channels) => {
if (!channels.some((channel) => channel.status === RPCChannelStatus.Resizing)) {
poller.stop();
enableRetry();
}
},
onError: (pollError) => showToast(getUserFacingMessage(pollError)),
}, 3000);
poller.start();
}
}

Insufficient Funds

import { InsufficientFundsError, NitroliteClient, getUserFacingMessage } from '@yellow-org/sdk-compat';

try {
await client.deposit(tokenAddress, 11_000_000n);
} catch (err) {
const typed = NitroliteClient.classifyError(err);
showToast(getUserFacingMessage(typed));

if (typed instanceof InsufficientFundsError) {
const tokenBalance = await client.getTokenBalance(tokenAddress);
renderFundingHelp({ tokenBalance, chainId: 11155111 });
}
}

Missing RPC URL

On-chain helpers throw No RPC URL configured for chain ... when blockchainRPCs is missing. Fix the client config with blockchainRPCs: { 80002: process.env.POLYGON_AMOY_RPC_URL! }.

import { NitroliteClient, getUserFacingMessage } from '@yellow-org/sdk-compat';

try {
await client.getOpenChannels();
} catch (err) {
const typed = NitroliteClient.classifyError(err);
showToast(getUserFacingMessage(typed));
if (err instanceof Error && err.message.includes('No RPC URL configured')) promptForRpcUrl();
}

Unsupported Asset or Wrong Amount Unit

try {
await client.transfer(destination, [{ asset: 'usdc', amount: '5000000' }]);
} catch (err) {
showToast(getUserFacingMessage(err));

if (err instanceof Error && err.message.includes('Unknown asset')) {
renderSupportedAssets(await client.getAssetsList());
}
}

If a transfer uses 5.0, fix it before retrying. Compat transfer uses raw asset-unit strings. Keep the amount-units table next to migrated payment code reviews.

Failed Checkpoint

Retry with capped backoff only after approval and state preconditions are satisfied. Keep the visible message behind getUserFacingMessage(err):

import { NitroliteClient, getUserFacingMessage } from '@yellow-org/sdk-compat';

let lastError: unknown;

for (const waitMs of [1000, 3000, 5000]) {
try {
await client.innerClient.checkpoint('usdc');
lastError = undefined;
break;
} catch (err) {
const typed = NitroliteClient.classifyError(err);
lastError = typed;
showToast(getUserFacingMessage(typed));
await new Promise((resolve) => setTimeout(resolve, waitMs));
}
}

if (lastError) {
throw lastError;
}