stride3d/stride · error · ArgumentOutOfRangeException

's must be finite and greater than zero

Error message

{owner}'s {fieldName} must be finite and greater than zero

What it means

ValidateGreaterThanZeroFinite validates that a float handed to the physics layer is both finite (not NaN/Infinity) and strictly greater than zero. Quantities like radius, size, or stiffness must be positive for shape construction and solver stability, so violations throw ArgumentOutOfRangeException with owner and field context.

Solutions

  1. Clamp before assigning: value = MathF.Max(MathF.Min(value, max), 1e-6f) after confirming it's finite.
  2. Fix the upstream computation or data source producing 0/NaN/Infinity.
  3. Validate configuration/deserialized values at load time and substitute sane defaults.

Example fix

// before
sphere.Radius = computedRadius; // could be 0 or NaN
// after
var r = float.IsFinite(computedRadius) && computedRadius > 0 ? computedRadius : 0.5f;
sphere.Radius = r;
Defensive patterns

Strategy: validation

Validate before calling

bool IsValidScalar(float v) => float.IsFinite(v) && v > 0;
if (!IsValidScalar(radius)) radius = 1e-3f; // or throw

Try / catch

try { fp.ValidateGreaterThanZeroFinite(this); prop = fp; } catch (ArgumentOutOfRangeException ex) { log.Error($"Invalid scalar for {ex.ParamName}", ex); }

Prevention

When it happens

Trigger: Setting a scalar physics property (e.g. SphereCollider radius, capsule length) to 0, a negative number, float.PositiveInfinity, or NaN — commonly from an uninitialized field or division by zero upstream.

Common situations: Reading collider dimensions from model/config data containing zeros; computing radius from bounds of an empty mesh; default(float) (0) accidentally passed through.

Related errors


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

Appendix: source

Thrown at sources/engine/Stride.BepuPhysics/Stride.BepuPhysics/Definitions/BepuAndStrideExtensions.cs:56

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static void ValidateRange<T>(this SVector3 vec, T owner, [CallerMemberName] string? fieldName = null)
    {
        if (NVector3.AllWhereAllBitsSet(NVector3.IsFinite(vec)) == false)
            throw new ArgumentOutOfRangeException($"{owner}'s {fieldName} must be finite");
    }

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static void ValidateRange<T>(this SQuaternion quat, T owner, [CallerMemberName] string? fieldName = null)
    {
        if (quat.IsNormalized == false)
            throw new ArgumentOutOfRangeException($"{owner}'s {fieldName} must be normalized");
    }

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static void ValidateGreaterThanZeroFinite<T>(this float fp, T owner, [CallerMemberName] string? fieldName = null)
    {
        if (fp <= 0 || float.IsFinite(fp) == false)
            throw new ArgumentOutOfRangeException($"{owner}'s {fieldName} must be finite and greater than zero");
    }
}

View on GitHub (pinned to 96fad776d2)