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 class | Code | Trigger | Recovery |
|---|---|---|---|
CompatError | varies | Base compat failure | Log error.code; show getUserFacingMessage(error) |
AllowanceError | ALLOWANCE_INSUFFICIENT | ChannelHub needs ERC-20 allowance | Approve, then retry |
UserRejectedError | USER_REJECTED | Wallet rejected a signature or transaction | Show retry UI; do not auto-loop prompts |
InsufficientFundsError | INSUFFICIENT_FUNDS | Not enough gas or token balance | Show funding guidance |
NotInitializedError | NOT_INITIALIZED | Wallet/client is disconnected | Reconnect and recreate the client |
OngoingStateTransitionError | ONGOING_STATE_TRANSITION | Previous transition still finalizing | Poll 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;
}