stride3d/stride · warning · IndexOutOfRangeException

This manifold is empty

Error message

This manifold is empty

What it means

EmptyManifold is a sentinel IContactManifold with zero contacts used by ContactEventsManager to represent manifolds with no contact points. Any attempt to index into it — here the Contact this[int] getter — has no contact to return and throws IndexOutOfRangeException('This manifold is empty').

Solutions

  1. Check manifold.Count > 0 before reading any contact.
  2. Loop with for (int i = 0; i < manifold.Count; i++) instead of a fixed range.
  3. Handle the empty case as 'no contacts / stopped touching' in your contact event handler.

Example fix

// before
var contact = manifold[0];
// after
if (manifold.Count > 0)
{
    var contact = manifold[0];
}
Defensive patterns

Strategy: validation

Validate before calling

if (manifold.Count > 0)
{
    var contact = manifold[0];
}

Type guard

static bool TryGetContact(IContactManifold m, int i, out Contact c) { if (i < m.Count) { c = m[i]; return true; } c = default; return false; }

Try / catch

try { var c = manifold[0]; } catch (IndexOutOfRangeException) { /* empty manifold: no contacts */ }

Prevention

When it happens

Trigger: Accessing the indexer of an EmptyManifold (e.g. manifold[0]) — iterating contact points of a manifold whose Count is 0 without checking Count first.

Common situations: Contact-event handler code that loops a fixed number of contacts instead of looping to manifold.Count; reading contact data when a pair stopped touching (manifold cleared to the empty sentinel).

Related errors


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

Appendix: source

Thrown at sources/engine/Stride.BepuPhysics/Stride.BepuPhysics/Definitions/Contacts/ContactEventsManager.cs:473

            }

            return false;
        }
    }

    [Flags]
    private enum Events
    {
        TouchingA = 0b01,
        TouchingB = 0b10,
    }


    private struct EmptyManifold : IContactManifold<EmptyManifold>
    {
        public int Count => 0;
        public bool Convex => true;
        public Contact this[int contactIndex] { get => throw new IndexOutOfRangeException("This manifold is empty"); set => throw new IndexOutOfRangeException("This manifold is empty"); }
        public static ref ConvexContact GetConvexContactReference(ref EmptyManifold manifold, int contactIndex) => throw new IndexOutOfRangeException("This manifold is empty");
        public static ref float GetDepthReference(ref EmptyManifold manifold, int contactIndex) => throw new IndexOutOfRangeException("This manifold is empty");
        public static ref int GetFeatureIdReference(ref EmptyManifold manifold, int contactIndex) => throw new IndexOutOfRangeException("This manifold is empty");
        public static ref Contact GetNonconvexContactReference(ref EmptyManifold manifold, int contactIndex) => throw new IndexOutOfRangeException("This manifold is empty");
        public static ref Vector3 GetNormalReference(ref EmptyManifold manifold, int contactIndex) => throw new IndexOutOfRangeException("This manifold is empty");
        public static ref Vector3 GetOffsetReference(ref EmptyManifold manifold, int contactIndex) => throw new IndexOutOfRangeException("This manifold is empty");
        public void GetContact(int contactIndex, out Vector3 offset, out Vector3 normal, out float depth, out int featureId) => throw new IndexOutOfRangeException("This manifold is empty");
        public void GetContact(int contactIndex, out Contact contactData) => throw new IndexOutOfRangeException("This manifold is empty");
        public float GetDepth(int contactIndex) => throw new IndexOutOfRangeException("This manifold is empty");
        public int GetFeatureId(int contactIndex) => throw new IndexOutOfRangeException("This manifold is empty");
        public Vector3 GetNormal(int contactIndex) => throw new IndexOutOfRangeException("This manifold is empty");
        public Vector3 GetOffset(int contactIndex) => throw new IndexOutOfRangeException("This manifold is empty");
    }
}

internal readonly record struct OrderedPair
{
    public readonly CollidableComponent A, B;

View on GitHub (pinned to 96fad776d2)