{"record":{"id":"c6b050c207f71e80","repo":"stride3d/stride","slug":"shapetype-does-not-consist-of-triangles","errorCode":null,"errorMessage":"{shapeType} does not consist of triangles","messagePattern":"(.+?) does not consist of triangles","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"sources/engine/Stride.Navigation/NavigationMeshBuilder.cs","lineNumber":529,"sourceCode":"\n                            Plane plane = new Plane(planeDesc.Normal, planeDesc.Offset)\n                            {\n                                // Pre-Transform plane parameters\n                                Normal = Vector3.TransformNormal(planeDesc.Normal, transform)\n                            };\n                            plane.Normal.Normalize();\n                            plane.D += Vector3.Dot(transform.TranslationVector, plane.Normal);\n\n                            colliderData.Planes.Add(plane);\n                        }\n                        else if (shapeType == typeof(ConvexHullColliderShape))\n                        {\n                            var hull = (ConvexHullColliderShape)shape;\n                            Matrix transform = hull.PositiveCenterMatrix * entityWorldMatrix;\n\n                            // V-HACD emits hull triangles in left-handed winding, matching the navmesh input convention.\n                            int[] indices = new int[hull.Indices.Count];\n                            if (hull.Indices.Count % 3 != 0) throw new InvalidOperationException($\"{shapeType} does not consist of triangles\");\n                            for (int i = 0; i < hull.Indices.Count; i++)\n                            {\n                                indices[i] = (int)hull.Indices[i];\n                            }\n\n                            entityNavigationMeshInputBuilder.AppendArrays(hull.Points.ToArray(), indices, transform);\n                        }\n                        else if (shapeType == typeof(StaticMeshColliderShape))\n                        {\n                            var mesh = (StaticMeshColliderShape)shape;\n                            Matrix transform = mesh.PositiveCenterMatrix * entityWorldMatrix;\n\n                            mesh.GetMeshDataCopy(out var verts, out var indices);\n\n                            // Convert hull indices to int\n                            if (indices.Length % 3 != 0) throw new InvalidOperationException($\"{shapeType} does not consist of triangles\");\n                            for (int i = 0; i < indices.Length; i += 3)\n                            {","sourceCodeStart":511,"sourceCodeEnd":547,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/engine/Stride.Navigation/NavigationMeshBuilder.cs#L511-L547","documentation":"During navmesh input building, a ConvexHullColliderShape's index buffer must be a triangle list (count divisible by 3). Throwing InvalidOperationException detects a corrupt or malformed hull index buffer before it would corrupt the built navmesh geometry.","triggerScenarios":"A ConvexHullColliderShape whose Indices.Count is not a multiple of 3 — usually from a hull generated by a broken/incompatible V-HACD version or truncated serialization of the convex hull asset.","commonSituations":"Convex hull assets regenerated by an external tool with a different index layout; assets serialized by an older Stride version then loaded by a newer one; manually constructed hulls with line/point indices mixed in.","solutions":["Regenerate the convex hull asset with the compatible V-HACD pipeline so Indices.Count is a multiple of 3","Validate/repair the offending collider's hull data (check Indices.Count % 3 == 0) before building the navmesh","Remove or replace the malformed convex hull collider (e.g. use a box/collider primitive) to unblock the build"],"exampleFix":"// before\nvar hull = ColliderShape as ConvexHullColliderShape; // malformed Indices\n// after\nif (hull != null && hull.Indices.Count % 3 != 0)\n{\n    // regenerate or fix the convex hull asset before building\n    throw new InvalidOperationException($\"Convex hull on {entity.Name} has non-triangle indices ({hull.Indices.Count})\");\n}","handlingStrategy":"validation","validationCode":"var hull = shape as ConvexHullColliderShape;\nif (hull != null && hull.Indices.Count % 3 != 0)\n    throw new InvalidOperationException(\"Convex hull indices are not a triangle list; regenerate the hull asset\");","typeGuard":"static bool IsTriangleList(ConvexHullColliderShape hull) => hull != null && hull.Indices.Count % 3 == 0;","tryCatchPattern":"try\n{\n    navigationMeshBuilder.Build();\n}\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"does not consist of triangles\"))\n{\n    // identify and fix/regenerate the offending convex hull collider\n}","preventionTips":["Regenerate convex hull assets whenever upgrading Stride or the hull-generation toolchain","Sanity-check hull index buffers after importing or editing collider assets","Prefer standard collider primitives where a convex hull is not required"],"tags":["csharp","mesh-data","convex-hull","navigation"],"backgroundTag":"schema-validation-failed","analyzedSha":"96fad776d210c221682aac1ccdf4c79dc046fc38","analyzedAt":"2026-09-14T02:59:31.279Z","contentChangedAt":"2026-09-14T02:59:31.279Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}