# Status & Errors

> Complete reference for Alpha Ladder MCP tool responses — the success wrapper, re-authentication errors, OTC quote errors (HTTP 410/409), validation errors, and how each one surfaces to an AI client.

Alpha Ladder MCP tools are a thin proxy over the Alpha Ladder backend. A successful call returns the tool's payload; a failed call is surfaced to the AI client as a **tool error**. This page documents every response and error shape you can encounter and the recommended handling for each.

---

## How errors reach the AI client

Understanding the mechanism first makes the rest of this page easier to handle correctly:

- **Success** — the tool returns its payload. Most AgentX tools wrap it in a standard success envelope (see below); a few return a bare value or array.
- **Failure** — when the backend returns a non-2xx HTTP status, the MCP layer does **not** return a normal payload. Instead the tool result is flagged as an **error result** (`isError`), and the error text is the backend's raw response body — usually a JSON string such as `{"message":"Service temporarily unavailable"}` or `{"success":false,"code":"QUOTE_EXPIRED","message":"..."}`.

**Practical consequence for agents:** when a tool call comes back as an error, read the error text — it carries the machine-readable `code`/`message` you need to decide what to do. Do not assume an error result is a transport failure to be blindly retried; most are deliberate business signals (expired quote, rate drift, validation failure) that retrying will not fix.

---

## Success wrapper

Most AgentX tools wrap their payload in a standard success envelope:

```json
{
  "success": true,
  "code": 200,
  "msg": "ok",
  "data": { ... }
}
```

| Field | Type | Description |
|---|---|---|
| `success` | boolean | **The authoritative success signal.** `true` if the operation completed; `false` on a soft failure (see OTC quote below). |
| `code` | number | Downstream business status code. Treat `success` — not a specific numeric value — as the source of truth, since the numeric scheme varies by backend subsystem. |
| `msg` | string | Human-readable status message. `"ok"` on success; a descriptive string on failure. |
| `data` | object or array | The result payload. Shape varies by tool. |

When `success` is `false`, read `msg` (and `code` where present) to determine the cause. Do not attempt to parse `data` on a failure response.

For AgentX tool-specific response shapes, see [AgentX — Response Reference](/developers/financial-services/responses).

---

## Re-authentication error shape

When a session has expired, or the server cannot authenticate the request, tools return a distinct error object **instead of** the standard success wrapper:

```json
{
  "error": true,
  "message": "Session expired",
  "authUrl": "https://www.alphaladder.hk/auth/..."
}
```

| Field | Type | Description |
|---|---|---|
| `error` | `true` (literal boolean) | Always `true` on re-authentication errors. |
| `message` | string | Human-readable description of why authentication is required. |
| `authUrl` | string (optional) | A URL the user must visit to re-authenticate. Present when action is required. |

**Handling:**

1. Check whether the response has an `error: true` field before processing the success wrapper.
2. If `authUrl` is present, surface it to the user and prompt them to re-authenticate. Do not silently redirect automated agents.
3. After the user completes authentication, retry the original tool call.
4. If `authUrl` is absent, the error is likely a server-side configuration issue — do not auto-retry.

---

## Transient service errors

When a backend step fails transiently — rather than rejecting the request on business grounds — the call is surfaced as a `503`:

| HTTP status | Error body | Meaning | Required action |
|---|---|---|---|
| `503 Service Unavailable` | `{ "message": "Service temporarily unavailable" }` | A downstream step failed transiently (not a validation or balance problem). | Transient. For safe read-only operations, a retry with exponential backoff is appropriate. If it persists, surface the failure to the user. Never auto-retry destructive operations on a `503`. |

---

## OTC quote & trade errors

The two-step OTC exchange flow has its own failure modes. They surface in two different ways depending on the step.

### `get_otc_quote` — soft failures (Step 1)

`get_otc_quote` returns a normal response with `success: false` (it does **not** raise an HTTP error):

```json
{ "success": false, "message": "Insufficient USD balance to exchange 100 USD for EUR." }
```

Typical causes are **insufficient balance**, an **unsupported currency pair**, or an **amount above the maximum / below the minimum**. Show `message` to the user, return them to currency selection, and do not auto-retry.

Additionally, if `get_otc_quote` succeeds but returns `exchangeRate: ""` or `finalAmount: ""`, the downstream pricing service cannot price that pair at that moment. Do not proceed to `confirm_otc_trade` — inform the user and let them retry later or choose a different pair.

### `confirm_otc_trade` — HTTP errors (Step 2)

`confirm_otc_trade` surfaces failures as **HTTP-level errors**, not as `{ "success": false }` payloads. The server re-fetches a fresh quote at confirm time and trades at the live rate, so two conditions can reject the confirmation:

| HTTP status | Error body | Meaning | Required action |
|---|---|---|---|
| `410 Gone` | `{ "success": false, "code": "QUOTE_EXPIRED", "message": "Quote expired or not found, please request a new quote." }` | The 5-minute server-side quote window elapsed before confirmation, or the quote context is gone. | Inform the user the quote has expired. Call `get_otc_quote` again to obtain a fresh quote before proceeding. |
| `409 Conflict` | `{ "success": false, "code": "PRICE_DRIFT_EXCEEDED", "message": "Exchange rate moved beyond tolerance (drift=…, tolerance=…), please request a new quote.", "data": { "originalPrice", "newPrice", "tolerance" } }` | The live market rate drifted beyond the system's tolerance from the originally quoted rate. | Inform the user the rate has changed. Call `get_otc_quote` again so they can review the updated rate before confirming. |

**Critical:** Do **not** auto-retry on `410` or `409`. Both conditions require the user to explicitly review a new quote. Auto-retrying a destructive financial operation without user review is unsafe.

For the full OTC two-step workflow, see [Exchange & OTC](/developers/financial-services/guides/exchange-otc).

---

## Validation errors

Requests with missing or malformed parameters are rejected before any business logic runs and surface as an **HTTP 400 Bad Request** tool error, with a message describing the offending field(s). Unknown/extra parameters are stripped rather than rejected.

These are caused by the AI client sending arguments that don't match a tool's schema. They are not retryable as-is — correct the arguments (consult the tool's parameter descriptions) and call again.

---

## General error-handling guidance

- **Never auto-retry destructive operations.** This includes `confirm_otc_trade` and `execute_fiat_withdrawal`. If either of these returns an error, surface it to the user and wait for explicit confirmation before attempting a new request.
- **Don't retry business errors.** `410`/`409` OTC errors, `400` validation errors, and `success: false` soft failures are deliberate signals — retrying without changing something (a fresh quote, corrected arguments) will fail again.
- **Retry only transient failures** — e.g. `503`, timeouts, or network errors on safe read operations such as `get_deposit_list` or `get_account_summary` — and only with exponential backoff. See [Rate Limits](/developers/reference/rate-limits) for backoff guidance.
- **Always surface the error message to the user.** MCP tools run in AI client contexts. When a tool returns an error, present its message in plain language rather than silently retrying or swallowing the failure.

---

## Cross-references

- [AgentX — Response Reference](/developers/financial-services/responses) — minor units, OTC trade codes, deposit/withdrawal status fields.
- [Rate Limits](/developers/reference/rate-limits) — request cadence guidance and backoff posture.
