Skip to content

Errors

Envelope

Every error the gateway itself produces uses one shape:

{
  "code": "UPSTREAM_ERROR",
  "message": "the aggregator refused: invalid input",
  "upstream": { "code": 40101, "msg": "invalid input" }
}

code is a stable SCREAMING_SNAKE_CASE token and is the field to branch on. message is human-readable and its wording is not part of the contract. upstream is present only when an engine supplied a body worth relaying, and its shape varies by engine (see Upstream detail).

Code reference

CodeHTTPMeaningRetryable
INVALID_REQUEST400A parameter or body field failed validationno, fix the request
NOT_A_PCSX_QUOTE400An aggregator quote was submitted as an orderno
INVALID_ORDER_BODY400PancakeSwap X rejected the order body's schemano
QUOTE_NOT_FOUND404Unknown quoteIdno, re-quote
ORDER_NOT_FOUND404Unknown order hashbriefly, after a submit
QUOTE_EXPIRED409The quote's validity window closedno, re-quote
UPSTREAM_ERROR502An engine failed or refused; also returned when every engine failedyes, with backoff
UPSTREAM_PAYLOAD_INVALID502An engine's response could not be interpretedyes, with backoff
QUOTE_TIMEOUT504No engine answered inside the time budgetyes
NO_ENGINE_AVAILABLE503No engine serves this chain and source selectionyes, or widen sources
DRAINING503This instance is shutting down and refuses new workyes, immediately
STORE_UNAVAILABLE503The gateway's quote store is unreachableyes
INTERNAL_ERROR500Defect in the gatewayyes, then report

Codes originating in PancakeSwap X submission are passed through unchanged so that clients already handling them need no translation:

CodeHTTP
ORDER_PARSE_FAIL400
INVALID_ORDER400
VALIDATION_ERROR400
CHAIN_NOT_SUPPORTED400
INSUFFICIENT_FUNDS400
QUOTE_EXPIRED409
TOO_MANY_OPEN_ORDERS429
CONCURRENT_REQUEST429
UNAUTHORIZED502
INTERNAL_ERROR502

INSUFFICIENT_FUNDS reports that the on-chain pre-flight failed because the swapper cannot cover the input amount, so prompt for a top-up rather than a re-sign. TOO_MANY_OPEN_ORDERS means the swapper has reached its cap on simultaneously open orders; wait for one to settle or expire.

Failures without the envelope

Three classes of failure do not carry the envelope. A parser that assumes code is always present will throw on them.

  • 400 with a framework-generated body, when a required query parameter is missing or a parameter cannot be coerced to its declared type (a non-numeric chainId, for example).
  • 422 with a framework-generated body, when a request body does not match the endpoint's schema. Posting a PancakeSwap X candidate to /v1/calldata, or an aggregator candidate to /v1/submit, lands here.
  • 401 or 403 with whatever body the edge produces, when a deployment enforces API keys and X-API-KEY is missing or unrecognised. The request never reaches the API, so no code of ours appears.

Parse defensively: read code when the body is JSON with that key, and fall back to the HTTP status otherwise.

Upstream detail

When present, upstream takes one of these forms:

ShapeOrigin
{"code": 40101, "msg": "invalid input"}An aggregator rejection, with its own numeric code
{"errorCode": "INSUFFICIENT_FUNDS", "detail": "…"}A PancakeSwap X submission rejection
{"error": "…"}A PancakeSwap X pricing rejection, or a schema rejection of the order body
{"status": 502, "body": "<html>…"}A response that was not interpretable at all, relayed 1:1 for diagnosis

The upstream object is for diagnosis and logging. Branch on the top-level code.

The field is populated on /v1/calldata, /v1/submit, and /v1/status, where a single engine call either succeeds or fails and its body can be relayed intact. It is absent on /v1/quote.

When every engine fails

If no engine produced a candidate, the outcome depends on why:

  • Every leg was cut off by the time budget: 504 QUOTE_TIMEOUT.
  • At least one leg failed for a reason of its own: 502 UPSTREAM_ERROR, with message naming each engine and its reason, for example agg: aborted; pcsx: no market maker quoted.