Skip to content
Errors

LCX Liberty. American DeFi. Your keys. Your assets. Your control.

Core concepts

Errors

The response envelope, and the codes worth branching on.

The envelope

Every response has the same outer shape, success or failure. Branch on success and then on code, rather than on the status alone.

json
{
  "success": false,
  "code": "no_route",
  "message": "No route found for this pair at this size."
}

message is written to be read by a person. In most cases it is the best thing you can put in front of a user verbatim. error carries the same string as code and exists only so older tooling keeps working; read code in new integrations.

Some codes carry extra fields beside the envelope. insufficient_liquidity is the richest: when the engine refuses a size it also searches for the sizes that would have worked, and reports them so your user does not have to guess.

json
{
  "success": false,
  "code": "insufficient_liquidity",
  "message": "This pair is indexed, but our liquidity is too thin at this size: the best route we found loses 96.19% of value. About 1.4 UNI trades at roughly 4.5% impact; the most we can quote at all is about 31.25 UNI (49.7% impact).",
  "bestImpactPct": 96.19,
  "venues": ["uniswap-v2", "uniswap-v3"],
  "maxAmountIn": "31250000000000000000",
  "maxAmountInImpactPct": 49.671,
  "comfortableAmountIn": "1400000000000000000",
  "comfortableImpactPct": 4.478
}

maxAmountIn is the largest input the engine verified it can still quote, and comfortableAmountIn is the largest it verified at no more than 5% impact. Both are raw units of tokenIn, both were re-quoted before being reported, and both can be null or absent: a pair can be too thin at any size, in which case only the generic message remains. venues names the venues of the single best route that was refused, not everything the search considered.

Codes

CodeStatusWhat to do
INVALID_API_KEY401Fix the key. Retrying will not help.
RATE_LIMITED429Back off and retry with jitter.
QUOTA_EXCEEDED429Upgrade or wait for the month to roll over.
no_route400The pair cannot be routed. Not retryable at this size.
insufficient_liquidity400Routable, but not at this size. The body carries maxAmountIn and comfortableAmountIn when the engine could verify working sizes; offer those instead of asking the user to guess.
pricing_unreliable409A pool behind this pair reports prices the engine refuses to trust (a stale or manipulated book). No size is safe; retry after the pool's state refreshes rather than shrinking the amount.
QUOTE_EXPIRED410Re-quote and show the new price. Do not retry the build.
price_moved400The pool moved past the floor the quote promised. Re-quote.
slippage_mismatch400The built floor no longer matches the quote. Re-quote; do not relax it.
store_unavailable503Our index for this chain is outside its freshness window, so we will not build against it. The message names which check failed. Retry shortly.
route_not_executable400The route contains a step the deployed router cannot run. Re-quote.
PERMIT_UNSUPPORTED400Fall back to a plain approve.
quote_unavailable503The engine could not price this in time. Ours, not yours. Retry shortly.

Retrying

Retry 5xx, network failures and RATE_LIMITED with jittered backoff. Do not retry any other 4xx. Resending a request the server has already refused will get the same answer, and it delays the moment you notice the bug.

Jitter is not decoration. Without it, every client that trips the same limit retries in lockstep and trips it again.

A failed request costs nothing, so the quota is not the reason to be careful here. Correctness is.