Errors
Errors come back in two places:
- In the HTTP response, when the request itself is wrong (bad field, expired token, not found).
- On the WebSocket, when the trading engine rejects an order or change after accepting the request (not enough margin, SL too close, market closed). See Orders are confirmed asynchronously.
A bot has to handle both.
REST errors
Same envelope as success, with success: false:
{
"success": false,
"code": 400,
"data": null,
"error": "Bad request",
"message": "volume is greater than position volume"
}
error is a generic label; message is the reason — log it.
| Status | Meaning | What to do |
|---|---|---|
| 400 | Bad request — a field is missing or invalid. | Fix the request; don't retry as is. |
| 401 | Missing, expired or invalid token. | Refresh the token and retry once. |
| 403 | Your scope can't do this (unauthorized to access this resource). | e.g. an API_Trader token calling reports, or an Investor session trading. |
| 404 | The order, position or symbol doesn't exist (or isn't yours). | Re-read state. |
| 429 | Too many auth calls from your IP. | Back off with jitter. |
| 500 | Server error. | Retry later with backoff; reconcile before resending an order. |
| 503 | A dependent service is unavailable. | Retry later. |
WebSocket errors
Error frames look like this:
{
"type": "bad_request",
"session_id": "f6a1c2d3-…",
"payload": { "message": "not enough free margin — this order needs 1082.34", "reason": "order_create" }
}
typeisbad_request,forbidden,not_found,unauthorizedorinternal_server_error.payload.reasonis the action that failed (order_create,position_update,position_close, …) — use it to settle your in-flight request.- A rejected order may instead arrive as
order_rejected, with the Order and itsrejection_msg.
Trading errors you'll see
When placing an order
| Message (abridged) | Cause |
|---|---|
couldn't create order, the market is closed for EURUSD | Outside the symbol's trading hours. |
lot size 0.001 is out of range — allowed 0.01 to 50.00 | volume outside min_value–max_value. |
not enough free margin — this order needs … | Not enough free margin for this size. |
you've reached the maximum number of open orders and positions (N) | Your broker's cap on open orders + positions. |
market order is not allowed / limit order is not allowed / stop order is not allowed | That order kind isn't enabled for the symbol (see its orders field). |
take profit is not allowed / stop loss is not allowed | SL/TP not enabled for the symbol. |
this order type is not allowed for EURUSD | The symbol is buy-only, sell-only, close-only or disabled (trade_level). |
buy limit price 1.09 must be less than or equal 1.08234 | Pending price on the wrong side of the market. |
stop loss price … must be less than or equal … / take profit price … must be greater than or equal … | SL/TP too close or on the wrong side — see the rules. |
expiration time should be at least 5 minutes from now | expiry_at too soon. |
invalid field type / invalid field side | Bad type, side, or expiration_policy value. |
When modifying or closing
| Message | Cause |
|---|---|
you can't update market order | Only pending orders can be modified. |
you can't update the order at this point | The order isn't pending anymore (filled, cancelled…). |
position is not open | Already closed or closing. |
volume is greater than position volume | Close volume larger than the position. |
invalid close amount 0.00 — it must be between 0 and the position volume | Close sent without volume. |
no live price available right now… | No recent tick for the symbol. Retry shortly. |
trading is currently disabled for this symbol | Broker disabled the symbol. |
Account-level
| Message | Cause |
|---|---|
unauthorized to access this resource (REST 403) / read-only (investor) session cannot place, modify or close trades (WebSocket forbidden) | An Investor (read-only) session tried to trade. |
this trial account has expired | Demo trial ended. |
account #N takes trades only from the MT4 mirror | The account is mirrored from MT4 and can't be traded directly. |