stride3d/stride · error · ArgumentOutOfRangeException

's must be finite

Error message

{owner}'s {fieldName} must be finite

What it means

ValidateRange(this SVector3, ...) is a guard extension that ensures a vector value handed to the physics engine contains only finite components (no NaN or +/-Infinity). Bepu physics cannot simulate non-finite numbers and would corrupt the broadphase/solver, so it throws ArgumentOutOfRangeException with owner and field name context.

Solutions

  1. Check float.IsFinite on each component before assigning, and fix the upstream computation producing NaN/Infinity.
  2. Clamp or substitute defaults for invalid values (e.g. Vector3.One) before passing to the physics property.
  3. Enable catching at the source: validate deserialized config/model data after load.

Example fix

// before
box.Size = new Vector3(1f / zeroScale); // NaN
// after
var s = zeroScale == 0 ? 1f : zeroScale;
box.Size = new Vector3(MathF.Max(1f / s, 1e-6f));
Defensive patterns

Strategy: validation

Validate before calling

bool IsFinite(SVector3 v) => float.IsFinite(v.X) && float.IsFinite(v.Y) && float.IsFinite(v.Z);
if (!IsFinite(value)) throw new ArgumentException("Vector must be finite before assignment");

Try / catch

try { vec.ValidateRange(this); property = vec; } catch (ArgumentOutOfRangeException ex) { log.Error($"NaN/Infinity in {ex.ParamName}", ex); }

Prevention

When it happens

Trigger: Setting a collider/body vector property (e.g. size, scale, position offsets) to a value containing NaN or Infinity, often from a division by zero or a bad input file upstream.

Common situations: Computing mesh bounds from an empty mesh, dividing by zero scale, or loading model data where a dimension is 0 leading to NaN in derived quantities.

Related errors


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

Appendix: source

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

    public static SRigidPose ToStride(this BRigidPose pose) => Unsafe.As<BRigidPose, SRigidPose>(ref pose);
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static BBodyVelocity ToBepu(this SBodyVelocity pose) => Unsafe.As<SBodyVelocity, BBodyVelocity>(ref pose);
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static SBodyVelocity ToStride(this BBodyVelocity pose) => Unsafe.As<BBodyVelocity, SBodyVelocity>(ref pose);
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static NVector3 ToNumeric(this SVector3 vec) => Unsafe.As<SVector3, NVector3>(ref vec);
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static SVector3 ToStride(this NVector3 vec) => Unsafe.As<NVector3, SVector3>(ref vec);
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static NQuaternion ToNumeric(this SQuaternion qua) => Unsafe.As<SQuaternion, NQuaternion>(ref qua);
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static SQuaternion ToStride(this NQuaternion qua) => Unsafe.As<NQuaternion, SQuaternion>(ref qua);

    [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)