dotnet/csharplang · error · ArgumentOutOfRangeException

{argumentExpression} ({argument}) cannot be less than {lowEx

Error message

{argumentExpression} ({argument}) cannot be less than {lowExpression} ({low}).

What it means

Thrown by an example `InRange(int argument, int low, int high)` helper from the caller-argument-expression proposal when `argument < low`. The message interpolates the CallerArgumentExpression-captured source text of each parameter (e.g. `argumentExpression`), the runtime value, and the bound, so the developer sees both the expression and the value that violated it.

Source

Thrown at proposals/csharp-10.0/caller-argument-expression.md:95

For argument validation, the attribute cannot be used directly, but can be made use of through a helper class:

```csharp
public static class Verify
{
    public static void Argument(bool condition, string message, [CallerArgumentExpression("condition")] string conditionExpression = null)
    {
        if (!condition) throw new ArgumentException(message: message, paramName: conditionExpression);
    }

    public static void InRange(int argument, int low, int high,
        [CallerArgumentExpression("argument")] string argumentExpression = null,
        [CallerArgumentExpression("low")] string lowExpression = null,
        [CallerArgumentExpression("high")] string highExpression = null)
    {
        if (argument < low)
        {
            throw new ArgumentOutOfRangeException(paramName: argumentExpression,
                message: $"{argumentExpression} ({argument}) cannot be less than {lowExpression} ({low}).");
        }

        if (argument > high)
        {
            throw new ArgumentOutOfRangeException(paramName: argumentExpression,
                message: $"{argumentExpression} ({argument}) cannot be greater than {highExpression} ({high}).");
        }
    }

    public static void NotNull<T>(T argument, [CallerArgumentExpression("argument")] string argumentExpression = null)
        where T : class
    {
        if (argument == null) throw new ArgumentNullException(paramName: argumentExpression);
    }
}

static T Single<T>(this T[] array)

View on GitHub (pinned to 05eb4800fc)

Solutions

  1. Validate the value is within `[low, high]` before calling InRange, and surface a clearer domain error to the caller if not.
  2. Clamp the input to the valid range: `argument = Math.Max(low, Math.Min(high, argument));` when a clamped fallback is acceptable.
  3. Correct the producer of the value (parse/format/config layer) so it cannot emit below-range numbers.
  4. Treat the lower bound as inclusive and adjust the caller's arithmetic if the boundary was meant to be exclusive.

Example fix

// before
Guard.InRange(count, 0, maxItems);

// after
int clamped = Math.Clamp(count, 0, maxItems);
Guard.InRange(clamped, 0, maxItems);
Defensive patterns

Strategy: validation

Validate before calling

static void EnsureInRange(int argument, int low, int high)
{
    if (argument < low || argument > high)
        throw new ArgumentOutOfRangeException(nameof(argument),
            $"{argument} is outside [{low}, {high}].");
}

Type guard

static bool IsWithin(int value, int low, int high) => value >= low && value <= high;

Try / catch

try { Guard.InRange(value, low, high); }
catch (ArgumentOutOfRangeException ex) when (ex.ParamName == nameof(value))
{
    // clamp or report the bound violation
}

Prevention

When it happens

Trigger: Calling `InRange(x, low, high)` with `x < low`. Passing a computed offset, count, or index that can dip below a documented minimum (often 0).

Common situations: Negative inputs where 0 is the floor; off-by-one in loops/size calculations; user-supplied configuration values (page size, retry count) clamped too loosely; deserialized data that skips UI-side bounds checks.

Related errors


AI-assisted analysis of dotnet/csharplang@05eb4800fc (2026-08-13). Data as JSON: /api/errors/3f74cdea57ac4c88. Report an issue: GitHub.