Skip to content

Errors

Every API failure throws AgentApiError with three pieces of information you can act on:

import { AgentApiError } from '@0xgasless/agent';
try {
await client.x402.pay({ agentId, to, value: '6000000' });
} catch (err) {
if (err instanceof AgentApiError) {
console.log(err.status); // 403
console.log(err.message); // 'per_tx_cap_exceeded'
console.log(err.code); // 'per_tx_cap_exceeded'
console.log(err.body); // { requestedUSD: '6.000000', perTxCapUSD: '5' }
}
}
FieldDescription
statusHTTP status from the platform — 400, 401, 403, 404, 500, 502.
messageShort human-readable message. Safe to log.
codeApp-level identifier when present (e.g. per_tx_cap_exceeded). Use this for branching logic, not message.
bodyRaw JSON body the server returned, including any extra context (requestedUSD, allowedChains, etc.).

You sent something the platform can’t process. Fix the request and retry.

message / codeCauseFix
agentId is requiredMissing required fieldProvide an agentId.
agentId must be alphanumeric, _ or -, max 64 charsInvalid agentId shapeMatch ^[A-Za-z0-9_-]{1,64}$.
value must be a positive integer stringvalue was empty, negative, or not a stringSend atomic units as a string, e.g. '500000'.
validBefore window cannot exceed 3600s (anti-replay)Asked for >1h validityKeep validBefore within 1 hour of now.
validAfter must be before validBeforeInverted windowSend validAfter < validBefore.
nonce must be 0x + 64 hex chars (32 bytes)Bad nonceLet the SDK generate it (default), or pass 32 valid bytes.
Chain "X" not allowed for free tierTier doesn’t allow that chainUse an allowed chain or upgrade your tier.
Token X not supported on YToken not registered for that chainSee Supported Chains.
Unsupported chainThe chain wasn’t registered with the facilitatorUse a supported chain.
messageCauseFix
Unauthorized — missing project contextMissing or malformed Authorization headerConfirm your API key is set in apiKey.
(any) — from npm install on a private packageOld / wrong API keyRegenerate the key in the dashboard.

The request was valid but the platform refused. Most policy violations land here.

codeBody extrasMeaning
per_tx_cap_exceededrequestedUSD, perTxCapUSDvalue exceeds the agent’s per-call cap.
per_day_cap_exceededrequestedUSD, perDayCapUSDToday’s running total + the requested value would breach the per-day cap. Resets at UTC midnight.
Chain X not in agent policyallowedChainsThe agent’s allowedChains doesn’t include the requested chain. Update with client.policy.setAgent().
Token X not in agent policyallowedTokensSame idea, for tokens.
Agent X is revoked — cannot signAgent is permanently revoked. Create a new agent.
Agent X is paused — cannot signAgent is paused. Reactivate via the dashboard.
Agent limit reached. <Tier> plan allows N agents.tier, limit, current, upgradeUrlYou’ve hit your tier’s agent cap. Revoke unused agents or upgrade.
x402 is not enabled for this projectx402Enabled: falseCall client.policy.enableX402() once.
messageCauseFix
Agent X not found in project YThe agent doesn’t exist (yet)Call client.agents.create().
Project Y not foundThe API key is somehow orphaned (rare)Generate a new key in the dashboard.

The platform reached an unexpected state or an upstream dependency failed.

messageCauseFix
Signing failed: ...KMS or HD derivation failedRetry; if persistent, contact support.
Spend tracking error: ...DynamoDB write failedRetry.
Facilitator: ... (502)The facilitator returned a non-2xxInspect err.body — usually a contract revert reason.
Facilitator: transaction execution revertedOn-chain settlement revertedCommon causes: agent holds none of the payment token (USDC/XSGD) on the chain; nonce reuse; agentURI too long (for identity); XSGD only — token paused or a party blacklisted by the issuer. Retry with a fresh nonce after fixing the cause.
Facilitator unreachable: ...Network issueRetry with backoff.
async function payWithRetry(input: PayInput, attempts = 3) {
for (let i = 0; i < attempts; i++) {
try {
return await client.x402.pay(input);
} catch (err) {
if (!(err instanceof AgentApiError)) throw err;
// 4xx is a client problem — don't retry
if (err.status >= 400 && err.status < 500) throw err;
// 5xx is transient — backoff and retry
await new Promise((r) => setTimeout(r, 500 * 2 ** i));
}
}
throw new Error(`Gave up after ${attempts} attempts`);
}
try {
await client.x402.pay({ agentId, to, value });
} catch (err) {
if (err instanceof AgentApiError && err.status === 403) {
switch (err.code) {
case 'per_tx_cap_exceeded':
// Maybe break the payment into smaller chunks
break;
case 'per_day_cap_exceeded':
// Wait for UTC midnight or fall back to a different agent
break;
default:
throw err;
}
}
}

Surface human-readable messages in your UI

Section titled “Surface human-readable messages in your UI”
function describeError(err: unknown): string {
if (err instanceof AgentApiError) {
if (err.code === 'per_tx_cap_exceeded') {
return `This payment is too large. Per-call cap is $${err.body?.perTxCapUSD}.`;
}
if (err.code === 'per_day_cap_exceeded') {
return `Daily spending cap reached. Resets at UTC midnight.`;
}
return err.message;
}
return String(err);
}
  • Payments — full list of policy checks that produce 403s.
  • Policy — how to widen agent caps.