stride3d/stride · error · IndexOutOfRangeException

'm' parameter should be between '-l' and '+l'.

Error message

'm' parameter should be between '-l' and '+l'.

What it means

SphericalHarmonics.CheckIndicesValidity validates the (l, m) indices used to address a spherical harmonic basis function. For a given degree l, the order m must satisfy |m| <= l; otherwise the index pair does not identify a valid harmonic. The library throws IndexOutOfRangeException with this message when Math.Abs(m) > l.

Solutions

  1. Clamp or validate m so that -l <= m <= l before calling the API.
  2. Fix loop bounds: iterate m from -l to l (inclusive) per degree l, not over a fixed range.
  3. Verify the l/m argument order was not swapped at the call site (a common convention mistake).
  4. Use LmToCoefficientIndex(l, m) consistently so coefficient indexing matches the validated (l, m) pairs.

Example fix

// before
sh.SetCoefficient(1, 2, value); // l=1, m=2 -> |m| > l
// after
int l = 1, m = 1;
if (Math.Abs(m) <= l)
    sh.SetCoefficient(l, m, value);
Defensive patterns

Strategy: validation

Validate before calling

int l = /* desired degree */, m = /* desired order */;
int maxOrder = 2; // library maxOrder, adjust per usage
if (l < 0 || l > maxOrder - 1)
    throw new ArgumentOutOfRangeException(nameof(l), $"'l' must be between 0 and {maxOrder - 1}.");
if (Math.Abs(m) > l)
    throw new ArgumentOutOfRangeException(nameof(m), $"'m' must be between -l and +l for l={l}.");

Try / catch

try
{
    sh.SetValue(l, m, value);
}
catch (IndexOutOfRangeException ex)
{
    // invalid (l, m) pair — clamp m to [-l, l] and retry or log
    int clamped = Math.Clamp(m, -l, l);
    sh.SetValue(l, clamped, value);
}

Prevention

When it happens

Trigger: Calling SphericalHarmonics evaluation/constructor helpers (e.g. SphericalHarmonics.FromBasicTerms / Evaluate-style APIs) with an (l, m) pair where l is within maxOrder-1 but m is outside [-l, +l], such as l=1 with m=2 or l=0 with m=-1.

Common situations: Hand-rolling loops over harmonic coefficients with wrong bounds (iterating m over the full order range instead of -l..l); porting shader or physics code that uses a different (m, l) convention; hardcoding indices without the |m|<=l constraint.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


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

Appendix: source

Thrown at sources/core/Stride.Core.Mathematics/SphericalHarmonics.cs:101

            CheckIndicesValidity(l, m, order);
            return Coefficients[LmToCoefficientIndex(l, m)];
        }
        set
        {
            CheckIndicesValidity(l, m, order);
            Coefficients[LmToCoefficientIndex(l, m)] = value;
        }
    }

    // ReSharper disable UnusedParameter.Local
    private static void CheckIndicesValidity(int l, int m, int maxOrder)
    // ReSharper restore UnusedParameter.Local
    {
        if (l > maxOrder - 1)
            throw new IndexOutOfRangeException("'l' parameter should be between '0' and '{0}' (order-1).".ToFormat(maxOrder - 1));

        if (Math.Abs(m) > l)
            throw new IndexOutOfRangeException("'m' parameter should be between '-l' and '+l'.");
    }

    private static int LmToCoefficientIndex(int l, int m)
    {
        return l * l + l + m;
    }
}

/// <summary>
/// A spherical harmonics representation of a cubemap.
/// </summary>
[DataContract("SphericalHarmonics")]
public class SphericalHarmonics : SphericalHarmonics<Color3>
{
    private readonly float[] baseValues;

    private const float Pi4 = 4 * MathUtil.Pi;
    private const float Pi16 = 16 * MathUtil.Pi;

View on GitHub (pinned to 96fad776d2)