Summary: That “array out of range” crash on Time[0] isn’t a bug in your logic. It’s a history data race condition. Here’s the fix.




Why Your EA Crashes on Time[0] and What 4066/4073 Actually Mean



I ran into this one a few years back on a VPS that had been running the same EA for eleven months without a hiccup. Then one Tuesday afternoon, the terminal log filled with “array out of range” at a line that only did one thing: read Time[0].

No logic change. No new build. The EA just decided that today was the day it would crash.

If you’ve hit this, you’re in a weird club. The MQL4 docs say Time[0] is “the current chart” — how can that go out of range? Let me walk through what’s actually happening, because the fix isn’t obvious and the official docs don’t spell it out.

What Actually Triggers This



Time[] is a series array. In MQL4, series arrays are time-ordered with index 0 being the most recent bar. The terminal maintains them, not your EA. When your EA calls Time[0], the terminal should just hand you the open time of the current bar.

But here’s the catch: “should” and “does” are different words.

There are two error codes that matter here, and they get conflated constantly:

  • 4066 — ERR_HISTORY_WILL_UPDATED. The requested history data is under updating. This is documented. The MQL4 reference explicitly says that when you request data from a different symbol or timeframe, you may get 4066 and need to retry after a delay.

  • 4073 — Data retrieval rejected by broker. This one is not in the mainstream docs. It surfaces when the broker’s server refuses a history request, often during connection instability, weekend rollover, or when the broker’s own feed has a hole.


  • The nasty part is that your EA can throw “array out of range” on Time[0] without either error being the direct cause. The terminal’s internal series array is momentarily empty or truncated during a history resync, and Time[0] becomes an access to a zero-length array. That’s a critical runtime error in MQL4 — division by zero, array out of bounds, and bad pointers all terminate the program immediately.

    You don’t get a graceful GetLastError() return. You get a dead EA.

    The Fix That Actually Works: iTime()



    After hitting this twice in six months, I stopped using Time[] in OnTick() entirely. Here’s why.

    iTime() is a function, not a series array access. It performs the bounds check internally and returns 0 (or a safe fallback) if the bar isn’t available, rather than crashing the program. It’s the same data, accessed through a wrapper that doesn’t blow up when the underlying buffer is transiently empty.

    ``mql4
    // Don’t do this in OnTick() without a guard
    datetime barTime = Time[0]; // can crash during history resync

    // Do this instead
    datetime barTime = iTime(Symbol(), Period(), 0);
    if(barTime == 0)
    {
    // history not ready — skip this tick
    return;
    }
    `

    The forum threads on this are sparse but consistent: traders who’ve dealt with 4073 specifically recommend
    iTime() as the safer wrapper. It won’t stop the broker from rejecting history requests, but it stops your EA from dying when that happens.

    What About ArrayCopySeries()?



    The official MQL4 reference offers
    ArrayCopySeries() as the “proper” way to pull series data from another symbol or timeframe. The documented pattern is:

  • Call ArrayCopySeries().

  • Check GetLastError() for 4066.

  • Retry with Sleep() if you got 4066.


  • That’s fine for cross-symbol or cross-timeframe requests. It’s overkill for
    Time[0] on the current chart, and it doesn’t solve the transient-truncation problem — ArrayCopySeries() can still return -1 or copy zero elements if the terminal is mid-resync.

    My honest take: if you’re reading the current chart’s time, just use
    iTime(). If you’re pulling history from a different symbol, use ArrayCopySeries() with the retry loop from the docs. Don’t mix the two approaches.

    The Nasty Little Detail Nobody Mentions



    There’s a second-order failure mode that took me embarrassingly long to figure out.

    When MT4 truncates chart bars (it has a hard limit of 50,000 bars on most builds), the series arrays shift. Values that were at index 0 move, buffers get refilled, and
    prev_calculated can be reset to zero. If your EA or indicator caches an array index from a previous tick and reuses it after a truncation event, you can get an out-of-range error that has nothing to do with Time[0] directly — but shows up on the same line because that’s where the chain of logic started.

    The fix here is boring but necessary: never cache series array indices across ticks without re-validating them. If you stored
    Time[5] five minutes ago and assumed it’s still the same bar, you’re wrong after any history truncation.

    A Minimal Guard Pattern I Use Now



    This is the stripped-down version I put at the top of
    OnTick() in every EA that touches price data:

    `mql4
    bool HistoryReady()
    {
    int bars = iBars(Symbol(), Period());
    if(bars < 10) // arbitrary minimum; adjust for your strategy
    return false;

    datetime t0 = iTime(Symbol(), Period(), 0);
    if(t0 == 0)
    return false;

    return true;
    }

    void OnTick()
    {
    if(!HistoryReady())
    {
    static datetime lastLog = 0;
    if(TimeCurrent() - lastLog > 3600) // log once per hour max
    {
    Print("History not ready — skipping tick");
    lastLog = TimeCurrent();
    }
    return;
    }

    // ... your actual logic ...
    }
    `

    The static
    lastLog is there because during a bad connection, you’ll get hundreds of these per minute and fill your log file.

    When It’s Not History at All



    One more thing before you go rewrite everything.

    If you’re getting “array out of range” on a line that looks like it’s reading
    Time[0] but actually involves a loop or a calculated index, check your loop bounds first. The MQL4 runtime error list is explicit: “going beyond array boundary” is a critical termination. A loop like:

    `mql4
    for(int i = 0; i <= Bars; i++) // <= is wrong here
    `

    will crash on the last iteration because
    Bars is a count, not the last valid index. This is a beginner mistake, but it disguises itself as the 4066/4073 problem because the error line looks innocent.

    Sources



    MQL4 Reference:
    ArrayCopySeries() — documented retry pattern for error 4066
    MQL4 Reference: Runtime Errors — array out of range as a critical termination
    MQL5 Forum thread on
    Time[0] array out of range and the iTime()` recommendation
    MQL5 Forum discussion on chart bar truncation and buffer invalidation at 50,000 bars

    This article was first published on FXEAR.com. Original content. Unauthorized reproduction prohibited.