Blog
MQL5 Array Out of Range Error: Causes and Safe Fix
Quick Answer
"Array out of range" is an MQL5 runtime error. Your code read or wrote an array index that does not exist, and the terminal stops the program. It shows up in the Experts tab, not at compile time.
The most common cause in an EA is reading an indicator buffer before it holds data, or reading more elements than CopyBuffer actually copied. The fix is to check BarsCalculated(), check the number CopyBuffer() returns, and check ArraySize() before you read an index.
Key Facts
| Item | Detail |
|---|---|
| Error type | Runtime, not a compile error |
| Where it appears | The Experts tab, with the file name, line and column |
| Typical cause | Index is greater than or equal to ArraySize() |
| Common trigger in EAs | CopyBuffer copied fewer values than requested |
| Common loop mistake | i <= ArraySize(arr) instead of i < ArraySize(arr) |
| Safe habit | Check the return value and the size before you read |
Compile Error vs Runtime Error
A compile error appears in MetaEditor and prevents the build. "Array out of range" is different. The code compiles, and the problem only appears when the program runs and reaches the bad index. A fixed index such as a[5] on double a[5] can sometimes be caught by the compiler. An index held in a variable cannot, so it fails at run time.
That is why the error often appears only in the Strategy Tester or on a live chart, and sometimes only on the first bars of the test.
Read the Log Line
The Experts tab prints a message like this:
array out of range in 'MyEA.mq5' (87,23)
The numbers are the line and the column. In MetaEditor, press Ctrl+G and enter the line number to jump to the exact statement. Look at every array access on that line. One of the indexes is outside the array.
Common Causes
- Loop off by one. The condition uses
<=where<is needed. CopyBuffercopied less than you asked for. You requested 3 values, got 1, and read index 2.- Indicator not ready. The handle is valid, but the indicator has not calculated enough bars yet, so the buffer is empty.
- Invalid indicator handle.
INVALID_HANDLEwas never checked, so everyCopyBuffercall fails. - Dynamic array never resized.
ArraySize()is 0, and you write to index 0. - Not enough history. The EA reads shift 5 on a chart that has only 3 bars loaded, which is common at the start of a test.
- Wrong index direction. The array is not set as a series, so index 0 is the oldest element and not the newest. See how bar shifts map from Pine Script.
The Loop Mistake
double values[];
ArrayResize(values, 5);
// Wrong: i reaches 5, but valid indexes are 0 to 4
for(int i = 0; i <= ArraySize(values); i++)
values[i] = 0.0;
// Right
for(int i = 0; i < ArraySize(values); i++)
values[i] = 0.0;
The Safe Pattern for Indicator Values
Create the handle once in OnInit() and check it. Then read values through a function that confirms the data is there before it touches the array.
int maHandle = INVALID_HANDLE;
int OnInit()
{
maHandle = iMA(_Symbol, _Period, 20, 0, MODE_SMA, PRICE_CLOSE);
if(maHandle == INVALID_HANDLE)
{
Print("Failed to create MA handle. Error: ", GetLastError());
return INIT_FAILED;
}
return INIT_SUCCEEDED;
}
void OnDeinit(const int reason)
{
if(maHandle != INVALID_HANDLE)
IndicatorRelease(maHandle);
}
bool ReadMA(int shift, double &value)
{
// BarsCalculated returns -1 on error, so this also covers that case
int calculated = BarsCalculated(maHandle);
if(calculated < shift + 1)
return false;
double buf[];
ArraySetAsSeries(buf, true);
int copied = CopyBuffer(maHandle, 0, shift, 1, buf);
if(copied != 1)
return false;
if(ArraySize(buf) < 1)
return false;
value = buf[0];
return true;
}
Because the start position is shift and count is 1, buf[0] holds the value at that shift. Use it in OnTick() like this:
void OnTick()
{
double ma;
if(!ReadMA(1, ma))
return; // data not ready, skip this tick
// use ma here
}
For more on the buffer functions themselves, see the MQL5 CopyBuffer guide.
Check History Before You Read Old Bars
If your logic looks back N bars, make sure the chart has them:
int needed = 50;
if(Bars(_Symbol, _Period) < needed)
return; // not enough history yet
Put this near the top of OnTick(). It stops the EA from reading bars that do not exist at the start of a backtest.
Reproduce the Error on Purpose
Seeing the error once makes it easier to recognize. Run this in a script on a demo chart:
void OnStart()
{
double data[3];
int index = 3; // valid indexes are 0, 1 and 2
Print(data[index]); // triggers: array out of range
}
Then change index to 2 and run it again. The error disappears.
Debugging Checklist
- Open the Experts tab and note the line and column.
- Press Ctrl+G in MetaEditor and jump to that line.
- Print
ArraySize()and the index right before the access. - Print the return value of
CopyBuffer()andBarsCalculated(). - Check that the indicator handle is not
INVALID_HANDLE. - Run the Strategy Tester and watch the first bars, where history is shortest.
If you are moving an indicator into an EA, the same buffer rules apply. Our guide on converting an MT5 indicator to an EA shows where these reads usually go wrong.
FAQ
What does array out of range mean in MQL5?
It means the program tried to access an array element at an index that does not exist. The terminal reports it as a runtime error and stops the program.
Why does the error only appear in the Strategy Tester?
The first bars of a test have little history, and indicators may not have calculated yet. Reads that are fine later on can fail at the start. Check Bars() and BarsCalculated() before you read.
Does CopyBuffer return an error if it copies fewer values?
It returns the number of elements copied, or -1 on failure. A return value lower than your requested count is not an exception. You must check it yourself.
How do I stop the EA from crashing on a bad index?
Check the index against ArraySize() before you use it, and have your read functions return false when data is missing. Then skip the tick instead of continuing.
Skip the Manual Buffer Handling
Buffer reads, handle checks and history guards are easy to get wrong when you convert a strategy by hand. CodeFlowOS generates MQL5 code you can review before you test it in the MT5 Strategy Tester. You can try it on the converter page.
This article is educational. It does not describe trading performance and is not financial advice. Always compile and test code in MetaEditor and the Strategy Tester before using it on a live account.