Runtime Error 201
Delphi Programming
Severity: ModerateWhat Does This Error Mean?
Runtime Error 201 is a range check error — a value or array index fell outside the permitted range for its type. For example, assigning 300 to a Byte variable (which only allows 0–255), or accessing MyArray[10] when the array only has 5 elements. This error only appears when range checking ({$R+}) is enabled in the compiler options.
Affected Models
- Delphi 12 Athens
- Delphi 11 Alexandria
- Delphi 10.4 Sydney
- Delphi 10.3 Rio
- Delphi 10.2 Tokyo
Common Causes
- Assigning a value larger or smaller than the target variable type allows (e.g., 300 into a Byte)
- Accessing an array element using an index outside the array's declared bounds
- A loop counter going one step past the last valid array index
- Casting a large integer to a smaller type (like Integer to Byte) without checking the value first
- Assigning a value outside the range of a subrange type or enumerated type
How to Fix It
-
Enable range checking during development. Add {$R+} at the top of your unit, or enable it globally via Project → Options → Compiler → Range checking. This makes Delphi catch out-of-range assignments at runtime.
You can disable it in release builds with {$R-} for performance, but always develop with it on so errors surface during testing.
-
Use the correct type for the variable's expected value range. If a value might exceed 255, use Word (0–65535) or Integer (-2 billion to +2 billion) instead of Byte.
Common Delphi integer types by range: Byte (0–255), ShortInt (-128–127), Word (0–65535), Integer (-2B to +2B), Cardinal (0–4B).
-
For array access, always guard the index with a bounds check: if (Index >= Low(MyArray)) and (Index <= High(MyArray)) then ... This prevents out-of-bounds access entirely.
Low() and High() return the first and last valid indexes of any array type in Delphi — they work for both static and dynamic arrays.
-
Review loop termination conditions. A for loop from 0 to Length(MyArray) will overshoot by one. Use 0 to Length(MyArray) - 1, or use a for-in loop which never has bounds issues.
For-in loops (for Item in MyArray do ...) handle bounds automatically and are the safest way to iterate arrays in modern Delphi.
-
Before casting a value to a narrower type, validate it first. Use a conditional to check that the value fits before performing the cast.
Example: if (Value >= 0) and (Value <= 255) then MyByte := Byte(Value) else raise ERangeError.Create('Value out of Byte range');
When to Call a Professional
Runtime Error 201 is always fixable by the developer. Enable range checking ({$R+}) during all development builds to catch these early. Use Low() and High() to safely reference array bounds instead of hard-coded numbers.
Frequently Asked Questions
Why does Runtime Error 201 only appear sometimes?
Runtime Error 201 only triggers when range checking is enabled in the compiler ({$R+}). With range checking off, out-of-range values silently wrap or truncate — for example, assigning 256 to a Byte gives 0 with no error. This silent data corruption is much harder to track down than an explicit runtime error, so always develop with range checking on.
What is the difference between Runtime Error 201 and an array access violation?
Runtime Error 201 is caught by Delphi's range checker before the memory access happens. An access violation (Runtime Error 216) happens at the OS level when your code actually reads or writes to an invalid memory address. Range checking is the safer guard — it catches the problem earlier with a clearer error message.
Can I leave range checking enabled in production builds?
Yes, the performance impact is usually very small. For most business applications, keeping {$R+} in production is worthwhile because it turns silent data corruption into an explicit, catchable exception. Only disable it in performance-critical inner loops where profiling shows a measurable difference.