# MetaTrader 4 API Errors & Rate Limits

> Index of every docs page as Markdown: [llms.txt](https://fxsocket.com/docs/llms.txt). All pages in one file: [llms-full.txt](https://fxsocket.com/llms-full.txt).

Source: https://fxsocket.com/docs/mt4/errors

Every error from the MetaTrader 4 API is machine-readable. Auth failures return a fixed code, and everything else (timeouts, validation, broker or MQL rejections) comes back in a uniform envelope you can branch on.

## Errors

A wrong or missing API key returns HTTP 401 with `UNAUTHORIZED` (see [Authentication](https://fxsocket.com/docs/mt4/authentication.md)). A read-only `fxs_ro_` key returns HTTP 403 with `READ_ONLY_KEY` on the trading routes and on any method other than GET or HEAD. An unknown account ID or path returns a plain 404 from the edge. Everything else (timeouts, validation failures, broker/MQL rejections) comes back in a uniform envelope with an `error` code, a `message`, and a `command_id` for log correlation:

```json
{
  "error": "MRPC_TIMEOUT",
  "message": "MarketInfo.PriceHistory timed out",
  "command_id": 19
}
```

5xx responses come in two flavors. A `500` or `504` with the envelope above means the terminal processed your request but the underlying operation failed or timed out, for example `{"error": "MRPC", "message": "CopyRates failed"}` when requesting history for a symbol your broker doesn't list (check `/symbols` for the exact spelling, suffixes included). Envelope-less 5xx responses mean the terminal itself is down or restarting, for example during the brief restart after an API-key rotation. Trading routes can briefly return 503 right after a terminal start, before the trade engine has registered.

## MT4 Trade Errors and Their Retcodes

A rejected order is not an error response: the request worked, the broker said no. It comes back as HTTP 200 with `success: false`. MT4 itself only reports an error number for that, so the bridge translates it into the matching MT5 `retcode` and puts the original number in `retcodeDescription`. Your code can branch on the same retcodes for MT4 and MT5 accounts, and the MT4 number is still there when you need it:

Rejected order on MT4:

```
{
  "success": false,
  "outcome": "rejected",
  "retcode": 10019,
  "retcodeDescription": "MT4 error 134: Not enough money",
  "deal": 0,
  "order": 0,
  ...
}
```

| MT4 error | Meaning | retcode |
| --- | --- | --- |
| 1 | No result: the order already has these values | `10025` No changes |
| 128 | Trade timeout | `10031` No connection |
| 129 | Invalid price | `10015` Invalid price |
| 130 | Invalid stops | `10016` Invalid stops |
| 131 | Invalid trade volume | `10014` Invalid volume |
| 132 | Market is closed | `10018` Market closed |
| 133 | Trade is disabled | `10017` Trading disabled |
| 134 | Not enough money | `10019` Not enough money |
| 135 | Price changed | `10015` Invalid price |
| 136 | Off quotes | `10021` No quotes |
| 138 | Requote | `10004` Requote |
| 139 | Order is locked | `10013` Invalid request |
| 145 | Modification denied, too close to market | `10016` Invalid stops |
| 146 | Trade context is busy | `10024` Too many requests |
| 148 | Too many open and pending orders | `10033` Order limit reached |
| 4108 | Invalid ticket | `10013` Invalid request |
| 4109 | Trading not allowed | `10017` Trading disabled |
| 4110 / 4111 | Long or short positions not allowed | `10017` Trading disabled |
| any other | Anything not listed above | `10006` Rejected |

A successful market order reports `10009` (Done), a placed pending order `10008` (Placed). `outcome` sums the result up as `applied`, `no_change` (retcode `10025`, safe to treat as applied), `partial` or `rejected`.

Requests MT4 cannot express at all never reach the broker. A stop-limit order (`BuyStopLimit`, `SellStopLimit`) is answered with HTTP 400 and `{"error": "MRPC_VALIDATION", "message": "stop-limit orders are not supported on MT4"}`. Error 146, trade context busy, means MT4 was still handling another order; MT4 processes one at a time, so retry shortly after.

## Rate Limits

Terminal requests are served by your own dedicated terminal, so heavy polling only slows down your own account, nobody else's. Platform routes under `/v1` are rate limited per API key: if you exceed a limit you get a `429` with a `Retry-After` header, so wait that long and retry. For live prices, positions, or account changes, prefer the [WebSocket streams](https://fxsocket.com/docs/mt4/websocket.md) over polling: you get pushed updates without burning round-trips.

## Related

- [Authentication](https://fxsocket.com/docs/mt4/authentication.md)
- [Trading](https://fxsocket.com/docs/mt4/trading.md)
- [WebSocket Streams](https://fxsocket.com/docs/mt4/websocket.md)
