stride3d/stride · error · InvalidOperationException

Inconsistency: two tetrahedra don't agree on their…

Error message

Inconsistency: two tetrahedra don't agree on their neighbour information (they should both reference each other)

What it means

CheckConnectivity (invoked from the BowyerWatsonTetrahedralization constructor) validates that neighbouring tetrahedra reference each other symmetrically. When a tetrahedron lists a neighbour, but that neighbour's own Neighbours array has no slot pointing back, the invariant is broken and InvalidOperationException is thrown.

Solutions

  1. Verify probe positions don't contain duplicates or near-degenerate configurations that stress the algorithm
  2. Reduce/simplify the probe layout and retry baking
  3. Report to Stride as an internal tetrahedralization bug if reproducible with a simple probe group
Defensive patterns

Strategy: try-catch

Validate before calling

if (probes.Select(p => p).Distinct().Count() != probes.Count)
    throw new ArgumentException("Duplicate probes can break tetrahedralization");

Try / catch

try { var t = new BowyerWatsonTetrahedralization(vertices); }
catch (InvalidOperationException e) { logger.Error(e, "Tetrahedralization connectivity failure"); /* fall back to brute-force lookup */ }

Prevention

When it happens

Trigger: A bug condition in AddVertex's cavity re-triangulation where an edge's recorded neighbour index doesn't match any face of the neighbour tetrahedron, detected during the constructor's connectivity pass.

Common situations: Practically only hit during light-probe baking on tetrahedralizations with many probes where numeric edge bookkeeping can diverge; indicates an engine bug rather than user error.

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


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

Appendix: source

Thrown at sources/engine/Stride.Rendering/Rendering/LightProbes/BowyerWatsonTetrahedralization.cs:484

                        // If edge is not shared by any other bad tetrahedra, it means it's a boundary of our polygonal hole
                        var neighbourTetrahedronIndex = tetrahedron->Neighbours[i];
                        if (badTetrahedra.BinarySearch(neighbourTetrahedronIndex) < 0)
                        {
                            var neighbourTetrahedronSelfIndex = -1;
                            if (neighbourTetrahedronIndex != -1)
                            {
                                // Find the neighbour index of current tetrahedra in neighbourTetrahedra
                                var neighbourTetrahedron = &tetrahedra[neighbourTetrahedronIndex];
                                for (int j = 0; j < 4; ++j)
                                {
                                    if (neighbourTetrahedron->Neighbours[j] == tetrahedronIndex)
                                    {
                                        neighbourTetrahedronSelfIndex = j;
                                        break;
                                    }
                                }
                                if (neighbourTetrahedronSelfIndex == -1)
                                    throw new InvalidOperationException("Inconsistency: two tetrahedra don't agree on their neighbour information (they should both reference each other)");
                            }

                            // Store edges information (to easily reconstruct neighbour after)
                            var vertex0 = tetrahedron->Vertices[(i + 1) % 4];
                            var vertex1 = tetrahedron->Vertices[(i + 2) % 4];
                            var vertex2 = tetrahedron->Vertices[(i + 3) % 4];

                            // If new vertex is at an odd position, it means that newly constructed tetrahedron would have a negative order, let's swap 2 vertices
                            //if (!IsTetrahedraPositiveOrder(ref vertex, ref vertices[vertex0], ref vertices[vertex1], ref vertices[vertex2]))
                            if (i % 2 == 1)
                            {
                                var vertexTemp = vertex1;
                                vertex1 = vertex2;
                                vertex2 = vertexTemp;
                            }

                            if (!IsTetrahedronPositiveOrder(ref vertex, ref vertices[vertex0], ref vertices[vertex1], ref vertices[vertex2]))
                                throw new InvalidOperationException();

View on GitHub (pinned to 96fad776d2)