stride3d/stride · error · ArgumentOutOfRangeException

Must be >= 0

Error message

Must be >= 0

What it means

Size3.Up2(count) computes a mip level size 'count' levels up by left-shifting Width, Height and Depth. A negative count would shift in the wrong direction and corrupt the mip math, so the library throws ArgumentOutOfRangeException requiring count >= 0.

Solutions

  1. Pass a non-negative count to Up2
  2. If the size must shrink, call Down2 with a positive count instead of Up2 with a negative one
  3. Validate or Math.Max(0, levelDelta) the computed mip delta before calling

Example fix

// before
var bigger = size.Up2(targetLevel - currentLevel); // negative if target < current
// after
var delta = targetLevel - currentLevel;
var bigger = delta >= 0 ? size.Up2(delta) : size.Down2(-delta);
Defensive patterns

Strategy: validation

Validate before calling

if (count >= 0) { var up = size.Up2(count); }

Type guard

bool IsValidMipDelta(int c) => c >= 0;

Try / catch

try { var up = size.Up2(count); }
catch (ArgumentOutOfRangeException ex) { /* ex.ParamName == "count"; clamp to 0 and retry */ }

Prevention

When it happens

Trigger: Calling size.Up2(-1) or any negative count, often from a mip-level variable that was decremented below zero or computed as (currentLevel - targetLevel) with swapped operands.

Common situations: Mip-chain generation loops where the level index underflows; passing relative level deltas that turn out negative; refactored code calling Up2 where Down2 was intended with a negative count.

Related errors


AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14). Data as JSON: /api/errors/c1958af4677c1778. Report an issue: GitHub.

Appendix: source

Thrown at sources/core/Stride.Core.Mathematics/Size3.cs:231

    /// Implements the !=.
    /// </summary>
    /// <param name="left">The left.</param>
    /// <param name="right">The right.</param>
    /// <returns>The result of the operator.</returns>
    public static bool operator !=(Size3 left, Size3 right)
    {
        return !left.Equals(right);
    }

    /// <summary>
    /// Calculates the next up mip-level (*2) of this size.
    /// </summary>
    /// <returns>A next up mip-level Size3.</returns>
    public readonly Size3 Up2(int count = 1)
    {
        if (count < 0)
        {
            throw new ArgumentOutOfRangeException(nameof(count), "Must be >= 0");
        }

        return new Size3(Math.Max(1, Width << count), Math.Max(1, Height << count), Math.Max(1, Depth << count));
    }

    /// <summary>
    /// Calculates the next down mip-level (/2) of this size.
    /// </summary>
    /// <param name="count">The count.</param>
    /// <returns>A next down mip-level Size3.</returns>
    public readonly Size3 Down2(int count = 1)
    {
        if (count < 0)
        {
            throw new ArgumentOutOfRangeException(nameof(count), "Must be >= 0");
        }

        return new Size3(Math.Max(1, Width >> count), Math.Max(1, Height >> count), Math.Max(1, Depth >> count));

View on GitHub (pinned to 96fad776d2)