Skip to content

Latest commit

 

History

History
86 lines (79 loc) · 7.23 KB

File metadata and controls

86 lines (79 loc) · 7.23 KB

Recipe — Error Recovery Strategy

Map each error.code returned by the envelope to a concrete recovery action. Use this table when wiring aigateway into an agent prompt or a control-flow layer.

error.code Exit Recommended Recovery
WALLET_NOT_CONFIGURED 1 Run aigateway wallet-init once (auto-creates a local session wallet).
SERVICE_URL_MISSING 1 Override via env AIGATEWAY_SERVICE_URL. The default service URL is wired into the CLI for production; this should never trigger in normal use.
AMOUNT_INVALID 1 Caller bug — input must be a positive numeric string (used by wallet-topup, wallet-gas, wallet-withdraw, --topup-amount).
AMOUNT_EXCEEDS_BALANCE 1 wallet-withdraw --amount exceeded available balance of --token. error.token says which asset; use smaller of requested vs. error.available.
NEEDS_AMOUNT 1 Non-TTY wallet-withdraw requires both --amount <n> and --token <symbol> (use the envelope's tokenSymbol/nativeSymbol). Re-run with both.
INVALID_WITHDRAW_TOKEN 1 wallet-withdraw --token must match the wallet's payment or gas token (envelope tokenSymbol/nativeSymbol). (Deprecated alias: INVALID_TOKEN.)
INSUFFICIENT_BALANCE 1 Top-up failed or the chosen --topup-amount was still below the call's required amount. Surface error.required / error.available; ask the user to retry with a larger top-up. (Deprecated alias: INSUFFICIENT_USDT.)
INSUFFICIENT_GAS 1 Approve / withdraw needs the native gas token. Run aigateway wallet-gas (WalletConnect, must be interactive), then retry. (Deprecated alias: INSUFFICIENT_BNB.)
NO_FUNDS 1 Nothing to withdraw. Inform the user; suggest wallet-topup if relevant.
NO_MAIN_WALLET 1 wallet-withdraw invoked with no mainWallet saved. Re-run with --to <address>.
MISSING_MODEL 1 sb invoke --model is required. Run aigateway sb tools to pick one.
MISSING_INPUTS 1 sb invoke --inputs is required, or the JSON is missing required fields. error.errors[] lists which fields are missing; error.required[] lists all required keys for the model.
INVALID_INPUTS 1 Inputs failed schema validation. error.errors[] items carry { field, kind, message } where kind ∈ {enum, type, range}. Fix and retry.
INVALID_INPUTS_JSON 1 --inputs could not be parsed as JSON. Check quoting / escaping; on shells use JSON.stringify(...) from your wrapper.
INPUTS_FILE_NOT_FOUND 1 --inputs @path file does not exist. Resolve to an absolute path or correct the caller.
INVALID_MODEL_ID 1 Server / catalog rejected the model id. Run aigateway sb tools --category <key> to find a valid one.
CATEGORY_NOT_FOUND 1 sb tools --category argument is not in the live catalog. Run aigateway sb tools (no filter) to list categories.
MODEL_PRICING_NOT_CONFIGURED 1 The catalog lists the model but the gateway has no price entry yet. Pick another model or ask the operator to add it.
INVALID_BODY 1 Server rejected the request body shape. Usually a CLI / catalog drift; file a bug.
TOPUP_REQUIRED 1 Non-TTY context, USDT below the per-call minimum. Choose from error.presets (filtered to ≥ error.minTopup) and rerun the failing command with --topup-amount <n>.
TOPUP_AMOUNT_TOO_SMALL 1 --topup-amount (or topup --amount) below error.minTopup. Rerun with a larger value.
PAYMENT_REJECTED 1 User cancelled in their wallet. Do not auto-retry — ask user first.
PAYMENT_TIMEOUT 2 WalletConnect approval window expired (5 min). Ask user whether to retry. Do not auto-retry.
WC_SESSION_EXPIRED 2 WalletConnect relay dropped the session. Re-run the original command.
TX_TIMEOUT 2 The on-chain transfer is likely still pending. Wait, then re-check with wallet-balance.
UPDATE_APPLIED 2 CLI just upgraded itself synchronously. The previous command was not executed. Surface error.fromerror.to and rerun the same command verbatim on the new version.
SERVICE_UNAVAILABLE 3 Exponential backoff: 1 s → 4 s → 16 s, max 3 attempts.
PAYMENT_FETCH_FAILED 3 First 402 probe failed. Backoff + retry; check network connectivity.
CATALOG_FETCH_FAILED 3 sb tools could not reach the server. Retry once; if it persists, sb invoke still runs (server-side validation is the safety net).
BALANCE_CHECK_FAILED 3 BSC RPC hiccup. Retry once after 2 s.
ALLOWANCE_CHECK_FAILED 3 BSC RPC hiccup. Retry once after 2 s.
TX_REVERTED 3 On-chain failure. Capture error.message for diagnosis; do not retry blindly.
WITHDRAW_FAILED 3 Withdraw transaction failed. Check aigateway wallet-balance and retry.
APPROVE_FAILED 3 One-time facilitator approve failed during wallet-topup. Inspect the tx; retry the top-up.
INVALID_PAYMENT_AMOUNT 3 Server-side issue (returned amount = 0). Retry after a short delay.
PAYMENT_FAILED 3 Service rejected the signed payment request. Surface error.data / error.status to the user / log. On 5xx, retry once.
IMAGE_DOWNLOAD_FAILED / DOWNLOAD_FAILED 3 The paid call succeeded but the local download failed. The original URL is still in the upstream response — surface it from data.downloaded[].url (when available) or re-fetch via --raw. Do not re-invoke the model (you'd pay again).
FUNDING_FAILED 3 Non-timeout / non-reject failure in the WalletConnect funding flow. Re-run wallet-topup.
INTERNAL_ERROR 4 File a bug. Don't retry.
WALLET_ERROR 1 Generic wallet failure. Surface to user, ask whether to retry.

Generic Retry Helper (Node.js)

async function withRetry(fn, { codes, attempts = 3, baseDelayMs = 1000 } = {}) {
  for (let i = 0; i < attempts; i++) {
    const { exitCode, envelope } = await fn();
    if (envelope.ok) return envelope;
    if (!codes.includes(envelope.error.code)) return envelope; // non-retryable
    if (i < attempts - 1) await new Promise(r => setTimeout(r, baseDelayMs * 4 ** i));
  }
}

// Only retry transient service/network errors
await withRetry(
  () => runAigateway([
    "sb", "invoke",
    "--model", "replicate/black-forest-labs/flux-schnell",
    "--inputs", JSON.stringify({ prompt: "a cyberpunk fox" }),
  ]),
  {
    codes: [
      "SERVICE_UNAVAILABLE",
      "PAYMENT_FETCH_FAILED",
      "CATALOG_FETCH_FAILED",
      "BALANCE_CHECK_FAILED",
      "ALLOWANCE_CHECK_FAILED",
      "INVALID_PAYMENT_AMOUNT",
    ],
  },
);

Anti-patterns

  • ❌ Don't retry PAYMENT_REJECTED or PAYMENT_TIMEOUT automatically — the user actively cancelled or walked away.
  • ❌ Don't retry IMAGE_DOWNLOAD_FAILED / DOWNLOAD_FAILED by re-invoking the model — the paid call already settled, you'd be charged again. Re-fetch the URL or re-run with --raw.
  • ❌ Don't match on error.message text — messages may change between versions. Match on error.code.
  • ❌ Don't ignore exit code in favour of envelope. Stack-level proxies sometimes mangle stdout; the exit code is a redundant safety net.
  • ❌ Don't paper over UPDATE_APPLIED by treating it as a generic timeout — it's a "new binary; rerun me" signal, not a failure.