Off Quotes & Requote in MT5: Fix Errors 10021 / 10004 (and MT4's 136 / 138)
Contents
- The family: what each code actually says
- ① TRADE_RETCODE_PRICE_OFF = 10021 (no quotes to process the request)
- ② TRADE_RETCODE_REQUOTE = 10004 (requote: a new price is offered)
- ③ MT4-era errors 136 / 138
- 30-second triage
- Causes & fixes (5 patterns)
- ① Fast market / news spikes (your price went stale in flight)
- ② `deviation` (slippage tolerance) is too tight
- ③ Execution mode: requotes are an *instant execution* phenomenon
- ④ Thin or stalled quotes: rollover, session open, illiquid symbols
- ⑤ Latency: your VPS is far from the broker's server
- MQL5 code that reduces these errors (for EA developers)
- Set `deviation` properly, in points
- Retry only the price retcodes — with a fresh tick each time
- Using the requoted price from 10004
- Better yet: don't order into bad windows
- Priority checklist
- Summary
- FAQ
- Q: Which is worse, 10004 or 10021?
- Q: My broker never requotes. Is it just better?
- Q: My MT4 EA reports error 136 / 138. Same fixes?
- Q: It never happens in backtests, only live.
Off Quotes & Requote in MT5 (10021 / 10004)
When your EA's log fills with off quotes (10021) or requote (10004), it looks like the broker is refusing your business — but these two are not money or lot-size problems. They are price problems. The price you sent and the price the server holds right now didn't match, and almost every case traces back to one of four things: a fast market, a too-tight slippage tolerance, the execution mode, or network latency.
This is a single, complete reference for 10021 (TRADE_RETCODE_PRICE_OFF), 10004 (TRADE_RETCODE_REQUOTE), and their MT4-era ancestors, errors 136 and 138 — what they mean, why they happen, the quick fixes, and the MQL5 code that handles them permanently. For the full list of error codes, see the complete MT5 error-code guide.
This article targets MT5 (build 4xxx) as of July 2026. Fine-grained behavior — whether the server requotes or simply fills at the new price — depends on the broker's execution model.
The family: what each code actually says
Price-mismatch rejections come in two flavors, distinguished by how the server answers.
① TRADE_RETCODE_PRICE_OFF = 10021 (no quotes to process the request)
Returned in MqlTradeResult.retcode after OrderSend(). The server is saying "there are no quotes to process the request" — either it has no valid price at that instant, or the price you sent is too far from the current quote to be processed.
Meaning : There are no quotes to process the request
Constant: TRADE_RETCODE_PRICE_OFF
Value : 10021
② TRADE_RETCODE_REQUOTE = 10004 (requote: a new price is offered)
Also an OrderSend() retcode, but this one is not a flat rejection — it's a counter-offer: "not at that price, but here's a new one." The server's re-quoted prices come back in the bid / ask fields of MqlTradeResult.
Meaning : Requote — the server offers a new price
Constant: TRADE_RETCODE_REQUOTE
Value : 10004
// Typical log output
2026.07.07 21:30:02.118 EA_NAME EURUSD,M5: OrderSend error 10004 (requote)
2026.07.07 21:30:02.310 EA_NAME EURUSD,M5: OrderSend error 10021
③ MT4-era errors 136 / 138
In MQL4 (MT4) the same phenomena surfaced as GetLastError() codes:
| MT4 constant | Value | MT5 equivalent |
|---|---|---|
ERR_OFF_QUOTES | 136 | 10021 (TRADE_RETCODE_PRICE_OFF) |
ERR_REQUOTE | 138 | 10004 (TRADE_RETCODE_REQUOTE) |
If you're reading an older EA's log or forum thread mentioning "error 136" or "error 138", everything in this article applies (the classic MT4 remedy was calling RefreshRates() before resending — the MQL5 equivalent is shown below).
How to read them in practice:
| retcode | What the server means | What the EA should do |
|---|---|---|
| 10004 (requote) | "The price moved; here's a new one" | resend at the fresh price (or walk away) |
| 10021 (price off) | "No quote I can process right now" | wait briefly, re-read the tick, resend |
Both are transient, retry-able errors. No setting or code change makes them impossible — but you can make them rare.
30-second triage
- Check when they happened (Journal timestamps)
- Clustered at NFP / FOMC / major news releases → a fast market doing fast-market things. Enable the EA's news filter if it has one
- Around server midnight (rollover) or the Monday open → thin, stale quotes; largely by design
- Random, at all hours → suspect latency, VPS location, or the
deviationsetting
- Check which symbol
- If it's concentrated on minors, exotics, or low-liquidity CFDs, the symbol's thin quote stream is the cause
- Try a manual order
- Manual one-click orders go through fine while the EA gets rejected → the EA's
deviation(slippage tolerance) is almost certainly too tight
- Manual one-click orders go through fine while the EA gets rejected → the EA's
These three checks tell you whether it's the market, the symbol, or your setup — then apply the matching fix below.
Causes & fixes (5 patterns)
① Fast market / news spikes (your price went stale in flight)
Symptom: 10004/10021 cluster exactly at economic releases, central-bank remarks, or the early Monday session.
Cause: between the moment your EA reads a tick and the moment the order reaches the server — tens to hundreds of milliseconds — the price moved several pips. The price you sent no longer exists, so the server requotes (10004) or reports no processable quote (10021). In a fast market this is normal physics, not a malfunction.
Fix:
- Block new entries around news (a news filter — FXEA365 EAs ship with
EconomicFilterbuilt in) - Widen
deviationto a realistic value (see ②) - Add a retry loop (code below)
② deviation (slippage tolerance) is too tight
Symptom: occasional rejections even in calm markets; manual orders fine, EA orders rejected.
Cause: MqlTradeRequest.deviation declares how many points of drift from your sent price you'll accept. Set it to 0 or a handful of points and an ordinary tick update is enough to get you rejected. A classic trap: the field is points, not pips — on a 5-digit broker, 1 pip = 10 points.
Fix:
- Start around 10–30 points (1–3 pips); 20 points is a sane default for anything that isn't a scalper
- Double-check you haven't confused pips and points ("deviation=5" meaning half a pip)
- If your strategy genuinely tolerates zero slippage, accept the rejections as intended behavior and only cap the retry count
③ Execution mode: requotes are an instant execution phenomenon
Symptom: broker A requotes constantly; broker B has never shown one.
Cause: requotes (10004) belong to instant execution. An instant order says "fill me at exactly this price," so when the price moves, the server counter-offers — a requote. Market execution says "fill me at whatever the market is now," so a requote is impossible by construction; instead you get filled at the moved price, i.e., slippage.
So "no requotes" doesn't mean "better broker" — it's a trade-off between being rejected and being slipped. You can check a symbol's mode in MT5 under Specification → Execution, or in code via SYMBOL_TRADE_EXEMODE.
Fix:
- Confirm your account's execution mode (most offshore standard accounts are market execution and never requote)
- If requotes disrupt your strategy, consider a market-execution account type or broker
- Note that market-execution brokers vary in whether they honor
deviationat all — if extreme slippage is unacceptable, audit your actual fills
④ Thin or stalled quotes: rollover, session open, illiquid symbols
Symptom: 10021 around server midnight (rollover), right after the weekly open, during holiday sessions, or on minor symbols.
Cause: at rollover, quote flow can pause briefly for swap processing and spreads blow out. Right after the Monday open, and on low-liquidity symbols generally, there simply isn't much of a quote to process. Ordering into that gets you 10021.
Fix:
- Avoid new entries roughly 23:55–00:05 server time (a time filter)
- Skip the first minutes after the weekly open (
AvoidMondayOpen-style settings) - Use a spread filter (
MaxSpread). Thin-quote periods always show widened spreads, so a spread filter sidesteps these windows automatically
⑤ Latency: your VPS is far from the broker's server
Symptom: more rejections than other setups regardless of time or symbol; high ping.
Cause: the longer the round trip to the trade server, the more the price can move in flight. Running an EA from a home PC, or from a VPS in a region far from the broker's server (typically London or New York), structurally raises the 10004/10021 rate. The ping shown at MT5's bottom-right corner is your first indicator — hundreds of ms is clearly bad; a few tens of ms or less is where you want to be.
Fix:
- Check the ping in MT5; if it's persistently high, fix the environment, not the code
- Move to a VPS close to the broker's server. Honestly, the latency-driven share of 10004/10021 cannot be coded away — physical proximity is the only cure. How to choose one is covered in the VPS guide for EAs
- The faster the EA (scalpers), the more latency matters; for H4/daily systems this cause is low priority
MQL5 code that reduces these errors (for EA developers)
Three principles: (1) set a realistic deviation in points, (2) on rejection, re-read the current tick and resend at the fresh price, (3) only retry the price-family retcodes.
Set deviation properly, in points
MqlTradeRequest req; MqlTradeResult res;
ZeroMemory(req); ZeroMemory(res);
req.action = TRADE_ACTION_DEAL;
req.symbol = _Symbol;
req.type = ORDER_TYPE_BUY;
req.volume = lots;
req.deviation = 20; // slippage tolerance: 20 points (= 2.0 pips on 5-digit)
// also set req.price / req.sl / req.tp / req.magic ...
deviation is in points. On 5-digit (or 3-digit JPY) symbols, 10 points = 1 pip. Zero or near-zero values inflate your rejection rate for no benefit.
Retry only the price retcodes — with a fresh tick each time
The two keys: call SymbolInfoTick() on every attempt (resending the stale price just earns the same rejection), and restrict retries to 10004/10021. Mechanically resending after "not enough money" (10019) or "invalid request" (10013) accomplishes nothing and pollutes your logs.
bool IsRetryableRetcode(uint rc)
{
return (rc == TRADE_RETCODE_REQUOTE // 10004
|| rc == TRADE_RETCODE_PRICE_OFF); // 10021
}
// Resend at fresh prices, at most 3 attempts, with a small backoff
bool SendWithRetry(MqlTradeRequest &req, MqlTradeResult &res, int maxTries = 3)
{
for(int attempt = 0; attempt < maxTries; attempt++)
{
MqlTick tick;
if(!SymbolInfoTick(req.symbol, tick))
{
Print("SymbolInfoTick failed: ", GetLastError());
return false;
}
req.price = (req.type == ORDER_TYPE_BUY) ? tick.ask : tick.bid;
if(OrderSend(req, res) && res.retcode == TRADE_RETCODE_DONE)
return true; // filled
if(!IsRetryableRetcode(res.retcode))
{
PrintFormat("OrderSend failed (no retry): retcode=%d", res.retcode);
return false; // don't retry non-price errors
}
PrintFormat("Retry %d/%d after retcode=%d", attempt + 1, maxTries, res.retcode);
Sleep(200 + 150 * attempt); // 200ms -> 350ms -> 500ms
}
Print("Order abandoned after retries (price kept moving).");
return false;
}
The backoff grows because hammering the server at 0 ms during a spike just collects identical rejections — but waiting too long drags your entry away from what the strategy intended, so give up after 2–3 attempts. Also note that pending orders (TRADE_ACTION_PENDING) return TRADE_RETCODE_PLACED (10008) on success, not TRADE_RETCODE_DONE.
Using the requoted price from 10004
On 10004, the server's counter-offer sits in MqlTradeResult.bid / ask. Re-reading the tick as above is sufficient in practice, but on instant execution you can implement "accept the requote if it's within tolerance" by comparing res.ask / res.bid against your intended price in points before resending.
Better yet: don't order into bad windows
Retrying is symptomatic treatment. Filters that block new entries around rollover, news, and widened spreads attack the cause:
// Spread filter: skip new entries while the spread is blown out
long spreadPts = SymbolInfoInteger(_Symbol, SYMBOL_SPREAD);
if(spreadPts > MaxSpreadPoints)
{
// thin-quote window — exactly when 10021 is most likely; stand aside
return;
}
The EAs distributed by FXEA365 ship with this spread filter, a news filter, and automatic retry on the price retcodes as standard equipment.
Priority checklist
| Priority | Check | Fix |
|---|---|---|
| 🚨 first | clustered at news releases / spikes? | enable the news filter; accept the rest as market physics |
| 🚨 first | deviation too tight? (unit = points) | 10–30 points; verify no pips/points mix-up |
| ⚠️ next | concentrated at rollover / Monday open / thin symbols? | time filter + spread filter |
| ⚠️ next | instant execution account? | consider market execution (trade-off: slippage) |
| ⚠️ next | high ping (hundreds of ms)? | move to a VPS near the broker server |
| 🛠 dev | retries limited to price retcodes? | fresh SymbolInfoTick each attempt, cap at 2–3 |
Summary
- 10021 (TRADE_RETCODE_PRICE_OFF) means "no quotes to process the request"; 10004 (TRADE_RETCODE_REQUOTE) means "here's a new price." Together with MT4's 136/138 they form the price-rejection family — nothing to do with funds or lot size.
- The causes collapse into five: fast markets, an over-tight
deviation, instant execution, thin-quote windows/symbols, and latency. - Requotes are an instant-execution phenomenon; market execution replaces them with slippage. "Never requotes" isn't a quality badge — it's a trade-off.
- Developers fix this permanently with a 2–3 attempt retry that re-reads the tick (10004/10021 only), a realistic
deviation, and time/spread filters. The latency-driven remainder yields only to physical proximity — a VPS near the broker.
For all error codes, see the complete MT5 error-code guide; for free EAs with these mitigations built in, see the EA list.
FAQ
Q: Which is worse, 10004 or 10021?
Neither — both are transient price-family errors of similar severity. 10004 means the server counter-offered a new price; 10021 means it had no processable quote. An occasional one is safe to ignore; only investigate when they cluster on specific times or symbols (news, rollover, deviation, latency).
Q: My broker never requotes. Is it just better?
More likely it uses market execution, where requotes are impossible by construction — price moves are absorbed as slippage on your fill instead. Rejected versus slipped is a trade-off, so audit your actual fill prices before crowning a winner.
Q: My MT4 EA reports error 136 / 138. Same fixes?
Yes. 136 (ERR_OFF_QUOTES) maps to 10021 and 138 (ERR_REQUOTE) to 10004, with identical causes. In MQL4 the standard remedy is calling RefreshRates() to update Bid/Ask before resending — the same idea as re-reading SymbolInfoTick() in MQL5.
Q: It never happens in backtests, only live.
Expected. The Strategy Tester has no (or heavily simplified) order-transit delay and no price movement during it, so 10004/10021 only exist forward. A clean backtest still needs live-side work: a sane deviation, a retry loop, and a low-latency environment.
Related
2026-07-07
AutoTrading Disabled in MT5: Fix Retcodes 10027 & 10026 (EA Not Trading)
2026-07-07
Invalid Stops in MT5: Fix Retcode 10016 & MT4 Error 130
2026-07-07
Market Closed in MT5: Fix Error 10018 & 132 (Even on Weekdays)
2026-07-07
Unsupported Filling Mode (MT5 Error 10030): The Fix When Your EA Stops Working on a New Broker
5-Day Email Course (Free)
Get one email a day covering the essentials of FX automated trading, how to read backtests correctly, and tips for choosing a broker.
* Privacy strictly protected. You can unsubscribe at any time.