MQL4 runtime error 4002

Fix array out of range in MQL4

MQL4 error 4002 means code tried to read or write an index outside the allocated array. For an array of size N, valid indexes are 0 through N minus 1. Check ArrayResize results, use i < ArraySize(array), and guard rates_total before accessing indicator series.

Open the Coding Agent, then choose MQL4 from the language menu.

SafeArrayLoop.mq4.mq4
#property strict

void OnStart()
  {
   double values[];
   int requested_size = 5;
   int actual_size = ArrayResize(values, requested_size);

   if(actual_size != requested_size)
     {
      Print("ArrayResize failed. Error ", GetLastError());
      return;
     }

   for(int i = 0; i < ArraySize(values); i++)
     {
      values[i] = (double)(i + 1);
     }

   int last_index = ArraySize(values) - 1;
   if(last_index >= 0)
      Print("Last value: ", values[last_index]);
  }
  • Valid indexes end at size minus 1
  • Check ArrayResize return values
  • Use rates_total in indicators
  • Respect series indexing direction

The off-by-one pattern behind error 4002

An array with five elements has indexes 0, 1, 2, 3, and 4. A loop using i <= ArraySize(values) eventually requests index 5 and crosses the boundary. The correct upper condition is i < ArraySize(values).

The same mistake appears in indicator buffers when code assumes rates_total is a valid index. It is a count, so the oldest valid element is rates_total minus 1.

PatternUnsafeGuard
Dynamic array loopi <= ArraySize(data)i < ArraySize(data)
Last elementdata[ArraySize(data)]data[ArraySize(data)-1] after size > 0
Indicator seriesclose[rates_total]close[rates_total-1] after rates_total > 0

ArrayResize does not make every index valid

ArrayResize changes only the first dimension of a dynamic array and returns the resulting element count or a failure value. Code should verify the returned size before filling the array.

Reserve capacity can reduce repeated physical allocations, but it does not increase the logical size reported by ArraySize. Index guards must use the logical element count.

  • Reject negative or zero requested sizes when the calculation requires data
  • Check copied element counts before indexing a destination array
  • Do not confuse reserved capacity with accessible elements
  • Recalculate cached indexes after resizing an array

Indicator arrays add a direction constraint

Timeseries normally use reverse indexing, while an ordinary dynamic array is indexed from left to right unless ArraySetAsSeries changes it. Combining arrays with different directions can produce a logically wrong value even when every index stays in bounds.

In OnCalculate, guard the minimum required bars and use prev_calculated only after handling the case where it returns to zero because deeper history was loaded.

Review the complete example

The loop condition is strictly less than ArraySize, and the final index is derived only after confirming the array is non-empty. The return value from ArrayResize is checked before any write.

A bounds fix prevents a runtime stop but does not prove the chosen index represents the intended bar or calculation window. Verify both safety and meaning.

SafeArrayLoop.mq4.mq4
#property strict

void OnStart()
  {
   double values[];
   int requested_size = 5;
   int actual_size = ArrayResize(values, requested_size);

   if(actual_size != requested_size)
     {
      Print("ArrayResize failed. Error ", GetLastError());
      return;
     }

   for(int i = 0; i < ArraySize(values); i++)
     {
      values[i] = (double)(i + 1);
     }

   int last_index = ArraySize(values) - 1;
   if(last_index >= 0)
      Print("Last value: ", values[last_index]);
  }
Where Pineify fits

Move from the rule to editable MQL4 source

Pineify can generate or revise one self-contained .mq4 file with MQL4-specific reference context. Its independent static checker returns MetaEditor diagnostics so you can repair source issues before testing in your own MT4 environment.

Open MQL4 Coding Agent

Static diagnostics do not prove runtime behavior, backtest results, broker compatibility, or live-trading safety.

Pineify MQL4 Coding Agent with MQL4 selected and an editable MetaTrader 4 code artifact

A practical workflow

  1. 1

    Read the failing line and index

    Identify the array, requested index, and logical size at the exact failure point.

  2. 2

    Replace count-as-index logic

    Use size minus one for a final element and strict less-than for loops.

  3. 3

    Guard allocation and copy results

    Check ArrayResize, Copy functions, and required history before indexing.

  4. 4

    Retest boundary cases

    Run with zero, one, and the minimum required number of elements.

Frequently asked questions

What is MQL4 array out of range error 4002?

Error 4002 reports an index outside an array boundary. In current MQL4 it is a critical runtime error that stops the program.

What is the last valid index of an MQL4 array?

The last valid index is ArraySize(array) minus 1, provided ArraySize returns a value greater than zero.

Should an MQL4 loop use less-than or less-than-or-equal?

Use i < ArraySize(array) when iterating from zero. Less-than-or-equal performs one extra iteration outside the array.

Can ArrayResize fail?

Yes. Check its returned size before using the new range. A failed or smaller allocation must not be treated as the requested size.

Why does an indicator fail only after history refresh?

A history update can reset prev_calculated to zero and change rates_total. Cached loop bounds that ignore this reset can address the wrong series range.

Last verified against the linked official references on . Compile and test the final source in the MetaTrader 4 build, broker, symbol, and account environment you plan to use.

Continue with one reviewable MQL4 file

Define the requirement, inspect the generated source, repair diagnostics, and test the behavior in your own MT4 environment.

Open Coding Agent