What it means
The program read or wrote an array element that doesn't exist: an index below 0, or equal to or above the array's size. It's a critical error. MetaTrader stops the program on the spot, so the rest of the handler doesn't run and the EA or indicator stops working. There's no GetLastError() code to catch: the check has to happen before the access.
Usual causes
- A copy that returned fewer values than you read.
CopyBuffer(),CopyRates()andCopyClose()return how many values they copied, or -1. An array that received 0 or 2 values and is read at index 2 is out of range. - An off-by-one loop.
for(int i = 0; i <= ArraySize(a); i++)reads one element too many. The last valid index issize - 1. - Series order confusion. After
ArraySetAsSeries(a, true), index 0 is the newest value; without it, the oldest. Code written for one order and run with the other reads past the end. - Indicator loops at the edges of history. Reading
close[i - period]at the start of the chart, orclose[i + 1]on the newest bar. - A dynamic array that was never sized with
ArrayResize().
How to detect it
- The Experts tab shows a line such as
array out of range in 'MyEA.mq5' (24,15): the file, then the line and column of the access. - Open the file in MetaEditor and go to that line: the array and the index are there. Print
ArraySize()and the index just before it to see the mismatch.
Broken code
This EA compiles. On a tick where the copy returns fewer than 3 values, reading ma[2] stops it with array out of range.
input int InpPeriod = 20; // Moving average period
int maHandle = INVALID_HANDLE;
int OnInit()
{
maHandle = iMA(_Symbol, PERIOD_CURRENT, InpPeriod, 0, MODE_EMA, PRICE_CLOSE);
return maHandle == INVALID_HANDLE ? INIT_FAILED : INIT_SUCCEEDED;
}
void OnTick()
{
double ma[];
ArraySetAsSeries(ma, true);
CopyBuffer(maHandle, 0, 0, 3, ma); // may copy fewer than 3 values, or none
// Reads index 2 without checking how many values arrived
if(ma[1] > ma[2])
Comment("EMA rising");
}Fixed code
The same program with the check that prevents the error. It compiles in MetaEditor with 0 errors and 0 warnings.
input int InpPeriod = 20; // Moving average period
int maHandle = INVALID_HANDLE;
int OnInit()
{
maHandle = iMA(_Symbol, PERIOD_CURRENT, InpPeriod, 0, MODE_EMA, PRICE_CLOSE);
return maHandle == INVALID_HANDLE ? INIT_FAILED : INIT_SUCCEEDED;
}
void OnTick()
{
double ma[];
ArraySetAsSeries(ma, true);
// Use the values only if all 3 arrived
if(CopyBuffer(maHandle, 0, 0, 3, ma) != 3)
return;
Comment(ma[1] > ma[2] ? "EMA rising" : "EMA not rising");
}
void OnDeinit(const int reason)
{
IndicatorRelease(maHandle);
Comment("");
}Why the fix works
CopyBuffer() returns the number of values it copied. Comparing it with the number requested before reading makes sure that indexes 0, 1 and 2 exist; when they don't, the EA waits for the next tick instead of crashing. The same rule applies to every array: compare the index with ArraySize() (or with what a copy function returned) before using it.
Questions
Can I catch array out of range with GetLastError()?
No. It's a critical error: MetaTrader stops the program before any of your code runs again, and MQL5 has no try/catch. The only fix is to check the index or the copied count before accessing the array.
Why does array out of range only happen sometimes?
Because the number of values available changes: on the first ticks after the EA starts, after a timeframe change, at the start of the chart's history, or when indicator data isn't ready. Code that assumes a fixed number of values breaks only in those moments.
What do the numbers in brackets mean?
The line and the column in the source file where the out-of-range access happened, for example (24,15) is line 24, column 15 of the file named before it.
The programs on this page are minimal examples written to show the error and its fix, not trading systems. Some of them send orders when they run: try them on a demo account. Trading involves substantial risk of loss and is not suitable for every investor. Edgoro is a software tool, not a broker or financial adviser: nothing it produces is investment advice, and past or backtested performance does not guarantee future results.