stride3d/stride · error · InvalidOperationException
Invalid state when computing tetrahedron
Error message
Invalid state when computing tetrahedron
What it means
BowyerWatsonTetrahedralization computes a tetrahedralization for light probe placement. While checking whether a point is inside a tetrahedron's circumsphere, it builds a plane for one of the four faces using a switch over face indices; if the face index is outside 0-3 the internal face-index table is corrupt, so the library throws InvalidOperationException rather than produce a wrong tetrahedralization.
Solutions
- Check for duplicate or exactly collinear light probe point coordinates in the input set and remove/offset them
- Verify no custom modifications to BowyerWatsonTetrahedralization broke the face-index table (indices 0-3)
- Capture the input point set and report a bug to Stride with a minimal reproducible probe layout
- Update Stride to the latest version in case the tetrahedralization bug was fixed upstream
Example fix
// before: duplicate probe positions collapse face bookkeeping
var points = new[] { p0, p1, p1, p2 };
// after: deduplicate points before tetrahedralization
var points = probePositions.Distinct().ToArray(); Defensive patterns
Strategy: try-catch
Validate before calling
// deduplicate and sanity-check probe points before tetrahedralization
var distinct = probePositions.Distinct().ToList();
if (distinct.Count < 4) throw new ArgumentException("Need at least 4 distinct probe points"); Type guard
bool IsValidProbeSet(IReadOnlyList<Vector3> pts) =>
pts.Distinct().Count() == pts.Count && pts.Count >= 4; Try / catch
try { var tetra = new BowyerWatsonTetrahedralization(points); ... }
catch (InvalidOperationException ex)
{
logger.LogError(ex, "Tetrahedralization failed; check probe point layout");
// fall back to grid-based probe placement
} Prevention
- Ensure probe points are distinct and not exactly collinear/coplanar in degenerate ways
- Do not modify the internal face-index logic of the algorithm
- Keep Stride updated for fixed numerical robustness in Predicates
When it happens
Trigger: Internal state corruption in the tetrahedralization: the infinityIndices / face-index mapping yields a value outside 0-3 when computing the bounding planes of the super-tetrahedron during InSphere checks. Only reachable via BowyerWatsonTetrahedralization with degenerate or duplicate probe points that corrupt the face bookkeeping.
Common situations: Custom light probe setups with coincident or collinear probe points, or a modified/patched copy of the algorithm breaking the face-index invariants; not normally reachable through supported public APIs.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- Tetrahedron not in positive order
- A disposed operation cannot be rollbacked.
- A disposed operation cannot be rollforwarded.
- Already initialized.
- Array cannot be empty or null.
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/cda8726753718d94.
Report an issue: GitHub.
Appendix: source
Thrown at sources/engine/Stride.Rendering/Rendering/LightProbes/BowyerWatsonTetrahedralization.cs:732
Vector3 normal;
switch (unused)
{
case 0:
normal = new Vector3(1.0f, 1.0f, 1.0f);
normal.Normalize();
break;
case 1:
normal = -Vector3.UnitZ;
break;
case 2:
normal = -Vector3.UnitY;
break;
case 3:
normal = -Vector3.UnitX;
break;
default:
throw new InvalidOperationException("Invalid state when computing tetrahedron");
}
var plane = new Plane(points[infinityIndices[0]], normal);
var result = Predicates.insphere(ref points[tetrahedronPointer->Vertices[0]], ref points[tetrahedronPointer->Vertices[1]], ref points[tetrahedronPointer->Vertices[2]], ref points[tetrahedronPointer->Vertices[3]], ref p);
return CollisionHelper.DistancePlanePoint(ref plane, ref p) > 0.0f;
}
else if (infinityCount == 2)
{
// Build a plane that contains both points not at infinity, and that is also parallel to the line formed by the two points at "infinity"
var infinitePerpendicularLine = points[infinityIndices[3]] - points[infinityIndices[2]];
var plane = new Plane(points[infinityIndices[0]], points[infinityIndices[1]], points[infinityIndices[0]] + infinitePerpendicularLine);
var result = Predicates.insphere(ref points[tetrahedronPointer->Vertices[0]], ref points[tetrahedronPointer->Vertices[1]], ref points[tetrahedronPointer->Vertices[2]], ref points[tetrahedronPointer->Vertices[3]], ref p);
return CollisionHelper.DistancePlanePoint(ref plane, ref p) > 0.0f;
}
else if (infinityCount == 1)
{
// 1 from super tetrahedra out of 4
// Find which one is usedView on GitHub (pinned to 96fad776d2)