DEV Community

Arnold Holm
Arnold Holm

Posted on

MT4 error 146: why a deferred signal needs a fresh quote

Your entry can wait: my MT4 test made 0 requests during 1 synthetic busy cycle and accepted a fresh-price simulated retry. I keep the signal pending while the terminal is busy, then check whether the entry still makes sense before sending it. That second check matters as much as waiting.

Native MT4 tester: deferred busy input and fresh-price simulated BUY

Waiting is a state change

A trader asked, “Is it a problem of broker , my internet connection or EA ?” in an MT4 discussion. Error 146 points to a busy trade context. It can tempt you into a small loop: try, wait, try the same request again.

But the request is getting older while it waits. The quote may move. The candle that produced the signal may no longer be the candle your rule permits. A pending order might already exist. A retry has to answer those questions before it sends anything.

I wanted a small check where the waiting decision and the later request were visible separately. I used my tester-only program in native MT4 build 1491, on EURUSD H4 history for 3 May 2021. The fixed tester spread was 20 points.

What the test actually did

The first step supplied a synthetic busy input. The program deferred that cycle and logged zero requests. It also checked that a busy input, a pending input and a stale quote blocked the relevant helper paths.

The native busy-context reading was false. With the later fresh-quote gate allowed, the program refreshed the prices. Ask was 1.2054 and Bid was 1.2034. The simulated BUY used Ask, returned ticket 1 and reported error 0.

The program selected that simulated ticket and checked its order type was BUY. It then closed the simulated position. The screenshot and Journal show the deferred step, the gates, the fresh-price request and the cleanup.

The two small gates

These are the exact helpers from that test:

bool CanSendNow(bool nativeBusy,bool syntheticPending){ return(!nativeBusy && !syntheticPending); }
bool CanRetryAfter(bool nativeBusyNow,bool quoteFresh){ return(!nativeBusyNow && quoteFresh); }
Enter fullscreen mode Exit fullscreen mode

The helpers answer narrow questions. They do not store a signal, coordinate several EAs or prove the request was accepted. The second helper only says the native busy reading is clear and the supplied quote-freshness check passes.

I would keep the actual OrderSend result separate from that permission. A terminal-state check is not a reservation of the trading context. Something can change between the check and the attempted send. Save the real result immediately, then decide whether the signal remains eligible for a later attempt.

Keep the original intent, refresh the market facts

The entry rule, side and signal identifier should remain attached to the deferred intent. Refreshing a quote must not quietly turn that intent into a different trade. Recompute the prices and protections required by the agreed rule, then compare the result with the signal's permitted age and conditions.

I would also distinguish an explicit rejection from an uncertain outcome. If you do not know whether the previous attempt created an order, inspect the terminal's orders and history before another send. Otherwise a network problem can become a duplicate-position problem.

Keep retries bounded. A loop that keeps asking until something succeeds can execute a signal long after the reason for entering has disappeared. Record why the request waited, when it became eligible again, and why the signal was kept or discarded.

Your five-minute check

Open one busy-context failure in your Journal and compare the request times from every EA on that terminal with the next retry and its quote time. Find the original signal time too. Does the retry log show a fresh quote, the original signal identity and a current decision to proceed?

If your bot loses that trail, the free Bug Check starts with the relevant source branch, one failure and the expected result.

This offline tester case used synthetic busy inputs and one simulated BUY, with zero account orders. It did not reproduce a real 146 rejection, concurrent EAs or current broker execution.

Top comments (0)