System.ArgumentOutOfRangeException

An ArgumentOutOfRangeException is thrown when an argument has a value outside the range that the method allows. It derives from ArgumentException, and adds the ActualValue property with the value that was passed in.

The message names the parameter, for example Index was out of range. Must be non-negative and less than the size of the collection (Parameter 'index'). The parameter name tells you which value to look for in your code.

Minimum version: >= 1.1 >= Core 1.0

Statistics

17
elmah.io logo 13

Common causes

A number that is too large, too small or negative was passed to a method. These are the usual ones.

An index outside a list

The indexer of a List<T> throws this exception when the index is below zero or at or above Count. Arrays throw an IndexOutOfRangeException instead.

var items = new List<string> { "a" };
var item = items[5];   // ArgumentOutOfRangeException

Check the index against Count, or use ElementAtOrDefault when a missing item is fine:

var items = new List<string> { "a" };
var index = 5;

var item = index >= 0 && index < items.Count ? items[index] : null;
var same = items.ElementAtOrDefault(index);

Substring, Remove and Insert throw when the start or the length goes past the end of the string. The values often come from a string that was shorter than expected.

var text = "abc";
var part = text.Substring(1, 10);   // ArgumentOutOfRangeException

Limit the length to what is left of the string:

var text = "abc";
var start = 1;
var length = Math.Min(10, text.Length - start);
var part = text.Substring(start, length);

Padding, buffers and sizes are often calculated from other lengths. When the input is longer than expected, the result is negative, and new string, new List and many other constructors reject it.

var title = "A very long product title";
var line = new string('-', 10 - title.Length);   // ArgumentOutOfRangeException

Make sure the value cannot go below zero:

var title = "A very long product title";
var line = new string('-', Math.Max(0, 10 - title.Length));

How to fix it and prevent it

Validate arguments in your own methods

The static helpers on ArgumentOutOfRangeException check common ranges in one line, and fill in the parameter name and the actual value.

public void SetQuantity(int quantity)
{
    ArgumentOutOfRangeException.ThrowIfNegativeOrZero(quantity);
}

Instead of calculating start and length by hand, use Take, Skip and Chunk for sequences. They never throw for a count that is too large.

var items = new List<int> { 1, 2, 3 };
var firstTen = items.Take(10).ToList();

The exception has ActualValue and ParamName. A log that includes them tells you which value was wrong without a debugger.

How to read the stack trace

The message names the parameter, and the frames show who passed the value:

System.ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection. (Parameter 'index')
   at System.Collections.Generic.List`1.get_Item(Int32 index)
   at Shop.Services.OrderLookup.ByIndex(Int32 index) in C:\src\Shop\Services\OrderLookup.cs:line 21
   at Program.<Main>$(String[] args) in C:\src\Shop\Program.cs:line 4

The parameter is index, and the indexer of List<T> rejected it. The call that passed it is on line 21 of OrderLookup.cs, so the next step is to find where that index came from, and why it was larger than the list.

Should you catch it?

Normally not. An index or length that is out of range is a bug in the code, and the fix is to check the value before the call.

For input that comes from users, validate it first and show an error message. Catching the exception is slower than a check, and can hide bugs.

Find ArgumentOutOfRangeException before your users do

elmah.io logs every unhandled exception in your .NET application with its stack trace and request details, groups identical errors and notifies you when a new one appears.

Start free trial
Free 21-day trial No credit card required

Related exceptions

Frequently asked questions

What is the difference from IndexOutOfRangeException?

Arrays and some built-in code throw an IndexOutOfRangeException. List<T> and most methods with a parameter throw an ArgumentOutOfRangeException and name the parameter.

Read ParamName and ActualValue on the exception. The message also includes the parameter name.

The start plus the length must not be larger than the string. A start of 5 in a string of 3 characters is out of range, whatever the length is.

Yes, for a numeric argument outside the allowed range. Use ThrowIfNegative and the other helpers, which set the parameter name for you.

Let your AI agent track it down

Connect Claude Code, Cursor, VS Code or Visual Studio to the elmah.io MCP server and ask your agent to look into ArgumentOutOfRangeException for you. For example:

AI chat
Find the most frequent ArgumentOutOfRangeException in my production log and show me the line that throws it.

The agent reads the stack trace and request details from elmah.io, finds the code in your repository and proposes a fix. In Claude Code, add the server with one command:

claude mcp add --transport http --client-id claudecode elmahio https://mcp.elmah.io/mcp

The MCP server is included on every plan and is currently in beta. Set up the MCP server.

Further reading

YouTube videos

Answers from Stack Overflow

What Is It?

This exception means that you're trying to access a collection item by index, using an invalid index. An index is invalid when it's lower than the collection's lower bound or greater than or equal to the number of elements it contains.

When It Is Thrown

Given an array declared as:

byte[] array = new byte[4];

You can access this array from 0 to 3, values outside this range will cause IndexOutOfRangeException to be thrown. Remember this when you create and access an array.

Array Length
In C#, usually, arrays are 0-based. It means that first element has index 0 and last element has index Length - 1 (where Length is total number of items in the array) so this code doesn't work:

array[array.Length] = 0;

Moreover please note that if you have a multidimensional array then you can't use Array.Length for both dimension, you have to use Array.GetLength():

int[,] data = new int[10, 5];
for (int i=0; i < data.GetLength(0); ++i) {
    for (int j=0; j < data.GetLength(1); ++j) {
        data[i, j] = 1;
    }
}

Upper Bound Is Not Inclusive
In the following example we create a raw bidimensional array of Color. Each item represents a pixel, indices are from (0, 0) to (imageWidth - 1, imageHeight - 1).

Color[,] pixels = new Color[imageWidth, imageHeight];
for (int x = 0; x <= imageWidth; ++x) {
    for (int y = 0; y <= imageHeight; ++y) {
        pixels[x, y] = backgroundColor;
    }
}

This code will then fail because array is 0-based and last (bottom-right) pixel in the image is pixels[imageWidth - 1, imageHeight - 1]:

pixels[imageWidth, imageHeight] = Color.Black;

In another scenario you may get ArgumentOutOfRangeException for this code (for example if you're using GetPixel method on a Bitmap class).

Arrays Do Not Grow
An array is fast. Very fast in linear search compared to every other collection. It is because items are contiguous in memory so memory address can be calculated (and increment is just an addition). No need to follow a node list, simple math! You pay this with a limitation: they can't grow, if you need more elements you need to reallocate that array (this may take a relatively long time if old items must be copied to a new block). You resize them with Array.Resize<T>(), this example adds a new entry to an existing array:

Array.Resize(ref array, array.Length + 1);

Don't forget that valid indices are from 0 to Length - 1. If you simply try to assign an item at Length you'll get IndexOutOfRangeException (this behavior may confuse you if you think they may increase with a syntax similar to Insert method of other collections).

Special Arrays With Custom Lower Bound
First item in arrays has always index 0. This is not always true because you can create an array with a custom lower bound:

var array = Array.CreateInstance(typeof(byte), new int[] { 4 }, new int[] { 1 });

In that example, array indices are valid from 1 to 4. Of course, upper bound cannot be changed.

Wrong Arguments
If you access an array using unvalidated arguments (from user input or from function user) you may get this error:

private static string[] RomanNumbers =
    new string[] { "I", "II", "III", "IV", "V" };

public static string Romanize(int number)
{
    return RomanNumbers[number];
}

Unexpected Results
This exception may be thrown for another reason too: by convention, many search functions will return -1 (nullables has been introduced with .NET 2.0 and anyway it's also a well-known convention in use from many years) if they didn't find anything. Let's imagine you have an array of objects comparable with a string. You may think to write this code:

// Items comparable with a string
Console.WriteLine("First item equals to 'Debug' is '{0}'.",
    myArray[Array.IndexOf(myArray, "Debug")]);

// Arbitrary objects
Console.WriteLine("First item equals to 'Debug' is '{0}'.",
    myArray[Array.FindIndex(myArray, x => x.Type == "Debug")]);

This will fail if no items in myArray will satisfy search condition because Array.IndexOf() will return -1 and then array access will throw.

Next example is a naive example to calculate occurrences of a given set of numbers (knowing maximum number and returning an array where item at index 0 represents number 0, items at index 1 represents number 1 and so on):

static int[] CountOccurences(int maximum, IEnumerable<int> numbers) {
    int[] result = new int[maximum + 1]; // Includes 0

    foreach (int number in numbers)
        ++result[number];

    return result;
}

Of course, it's a pretty terrible implementation but what I want to show is that it'll fail for negative numbers and numbers above maximum.

How it applies to List<T>?

Same cases as array - range of valid indexes - 0 (List's indexes always start with 0) to list.Count - accessing elements outside of this range will cause the exception.

Note that List<T> throws ArgumentOutOfRangeException for the same cases where arrays use IndexOutOfRangeException.

Unlike arrays, List<T> starts empty - so trying to access items of just created list lead to this exception.

var list = new List<int>();

Common case is to populate list with indexing (similar to Dictionary<int, T>) will cause exception:

list[0] = 42; // exception
list.Add(42); // correct

IDataReader and Columns
Imagine you're trying to read data from a database with this code:

using (var connection = CreateConnection()) {
    using (var command = connection.CreateCommand()) {
        command.CommandText = "SELECT MyColumn1, MyColumn2 FROM MyTable";

        using (var reader = command.ExecuteReader()) {
            while (reader.Read()) {
                ProcessData(reader.GetString(2)); // Throws!
            }
        }
    }
}

GetString() will throw IndexOutOfRangeException because you're dataset has only two columns but you're trying to get a value from 3rd one (indices are always 0-based).

Please note that this behavior is shared with most IDataReader implementations (SqlDataReader, OleDbDataReader and so on).

You can get the same exception also if you use the IDataReader overload of the indexer operator that takes a column name and pass an invalid column name.
Suppose for example that you have retrieved a column named Column1 but then you try to retrieve the value of that field with

 var data = dr["Colum1"];  // Missing the n in Column1.

This happens because the indexer operator is implemented trying to retrieve the index of a Colum1 field that doesn't exist. The GetOrdinal method will throw this exception when its internal helper code returns a -1 as the index of "Colum1".

Others
There is another (documented) case when this exception is thrown: if, in DataView, data column name being supplied to the DataViewSort property is not valid.

How to Avoid

In this example, let me assume, for simplicity, that arrays are always monodimensional and 0-based. If you want to be strict (or you're developing a library), you may need to replace 0 with GetLowerBound(0) and .Length with GetUpperBound(0) (of course if you have parameters of type System.Array, it doesn't apply for T[]). Please note that in this case, upper bound is inclusive then this code:

for (int i=0; i < array.Length; ++i) { }

Should be rewritten like this:

for (int i=array.GetLowerBound(0); i <= array.GetUpperBound(0); ++i) { }

Please note that this is not allowed (it'll throw InvalidCastException), that's why if your parameters are T[] you're safe about custom lower bound arrays:

void foo<T>(T[] array) { }

void test() {
    // This will throw InvalidCastException, cannot convert Int32[] to Int32[*]
    foo((int)Array.CreateInstance(typeof(int), new int[] { 1 }, new int[] { 1 }));
}

Validate Parameters
If index comes from a parameter you should always validate them (throwing appropriate ArgumentException or ArgumentOutOfRangeException). In the next example, wrong parameters may cause IndexOutOfRangeException, users of this function may expect this because they're passing an array but it's not always so obvious. I'd suggest to always validate parameters for public functions:

static void SetRange<T>(T[] array, int from, int length, Func<i, T> function)
{
    if (from < 0 || from>= array.Length)
        throw new ArgumentOutOfRangeException("from");

    if (length < 0)
        throw new ArgumentOutOfRangeException("length");

    if (from + length > array.Length)
        throw new ArgumentException("...");

    for (int i=from; i < from + length; ++i)
        array[i] = function(i);
}

If function is private you may simply replace if logic with Debug.Assert():

Debug.Assert(from >= 0 && from < array.Length);

Check Object State
Array index may not come directly from a parameter. It may be part of object state. In general is always a good practice to validate object state (by itself and with function parameters, if needed). You can use Debug.Assert(), throw a proper exception (more descriptive about the problem) or handle that like in this example:

class Table {
    public int SelectedIndex { get; set; }
    public Row[] Rows { get; set; }

    public Row SelectedRow {
        get {
            if (Rows == null)
                throw new InvalidOperationException("...");

            // No or wrong selection, here we just return null for
            // this case (it may be the reason we use this property
            // instead of direct access)
            if (SelectedIndex < 0 || SelectedIndex >= Rows.Length)
                return null;

            return Rows[SelectedIndex];
        }
}

Validate Return Values
In one of previous examples we directly used Array.IndexOf() return value. If we know it may fail then it's better to handle that case:

int index = myArray[Array.IndexOf(myArray, "Debug");
if (index != -1) { } else { }

How to Debug

In my opinion, most of the questions, here on SO, about this error can be simply avoided. The time you spend to write a proper question (with a small working example and a small explanation) could easily much more than the time you'll need to debug your code. First of all, read this Eric Lippert's blog post about debugging of small programs, I won't repeat his words here but it's absolutely a must read.

You have source code, you have exception message with a stack trace. Go there, pick right line number and you'll see:

array[index] = newValue;

You found your error, check how index increases. Is it right? Check how array is allocated, is coherent with how index increases? Is it right according to your specifications? If you answer yes to all these questions, then you'll find good help here on StackOverflow but please first check for that by yourself. You'll save your own time!

A good start point is to always use assertions and to validate inputs. You may even want to use code contracts. When something went wrong and you can't figure out what happens with a quick look at your code then you have to resort to an old friend: debugger. Just run your application in debug inside Visual Studio (or your favorite IDE), you'll see exactly which line throws this exception, which array is involved and which index you're trying to use. Really, 99% of the times you'll solve it by yourself in a few minutes.

If this happens in production then you'd better to add assertions in incriminated code, probably we won't see in your code what you can't see by yourself (but you can always bet).

The VB.NET side of the story

Everything that we have said in the C# answer is valid for VB.NET with the obvious syntax differences but there is an important point to consider when you deal with VB.NET arrays.

In VB.NET, arrays are declared setting the maximum valid index value for the array. It is not the count of the elements that we want to store in the array.

' declares an array with space for 5 integer 
' 4 is the maximum valid index starting from 0 to 4
Dim myArray(4) as Integer

So this loop will fill the array with 5 integers without causing any IndexOutOfRangeException

For i As Integer = 0 To 4
    myArray(i) = i
Next

The VB.NET rule

This exception means that you're trying to access a collection item by index, using an invalid index. An index is invalid when it's lower than the collection's lower bound or greater than equal to the number of elements it contains. the maximum allowed index defined in the array declaration

By Adriano Repetti. Read the original answer on Stack Overflow.

Your getting this error because when you validation finds that there are no issues, the Errors collection returns with no items, and the following binding logic fails:

Path=(Validation.Errors)[0].ErrorContent}"

you are accessing the validation collection by a specific index. I'm currently working on a DataTemplate Suggestion for replacing this text.

I love that Microsoft listed this in their standard example of a validation template.

update so replace the code above with the following, and the binding logic will know how to handle the empty validationresult collection:

Path=(Validation.Errors).CurrentItem.ErrorContent}"

(following xaml was added as a comment)

<ControlTemplate x:Key="ValidationErrorTemplate" TargetType="Control">
    <StackPanel Orientation="Horizontal">
        <TextBlock Foreground="Red" FontSize="24" Text="*" 
                   ToolTip="{Binding .CurrentItem}">
        </TextBlock>
        <AdornedElementPlaceholder>
        </AdornedElementPlaceholder>
    </StackPanel>
</ControlTemplate>

Update in 2019

As of currently, the correct path syntax to use is:

Path=(Validation.Errors)/ErrorContent

By Nathan Tregillus. Read the original answer on Stack Overflow.

You can set using SelectedIndex (which uses a zero-based index)

comboBox1.SelectedIndex = 0;

OR

SelectedItem

comboBox1.SelectedItem = "your value"; // 

The latter won't throw an exception if the value is not available in the combobox

EDIT

If the value to be selected is not specific then you would be better off with this

comboBox1.SelectedIndex = comboBox1.Items.Count - 1;

By V4Vendetta. Read the original answer on Stack Overflow.

new DateTime() is 01/01/0001 00:00:00 which is also DateTime.MinValue.

You are subtracting one hour from that.

Guessing you are trying to subtract an hour from the TimeTo value:

var TimeFrom = TimeTo.AddHours(-1);

By Oded. Read the original answer on Stack Overflow.

OK. I've found how to do this. Here's the final code:

    public static string ComputeMD5(string str)
    {
        var alg = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Md5);
        IBuffer buff = CryptographicBuffer.ConvertStringToBinary(str, BinaryStringEncoding.Utf8);
        var hashed = alg.HashData(buff);
        var res = CryptographicBuffer.EncodeToHexString(hashed);
        return res;
    }

By Alireza Noori. Read the original answer on Stack Overflow.