stride3d/stride · error · InvalidOperationException
does not consist of triangles
Error message
{shapeType} does not consist of triangles What it means
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.
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
Example fix
// before
var hull = ColliderShape as ConvexHullColliderShape; // malformed Indices
// after
if (hull != null && hull.Indices.Count % 3 != 0)
{
// regenerate or fix the convex hull asset before building
throw new InvalidOperationException($"Convex hull on {entity.Name} has non-triangle indices ({hull.Indices.Count})");
} Defensive patterns
Strategy: validation
Validate before calling
var hull = shape as ConvexHullColliderShape;
if (hull != null && hull.Indices.Count % 3 != 0)
throw new InvalidOperationException("Convex hull indices are not a triangle list; regenerate the hull asset"); Type guard
static bool IsTriangleList(ConvexHullColliderShape hull) => hull != null && hull.Indices.Count % 3 == 0;
Try / catch
try
{
navigationMeshBuilder.Build();
}
catch (InvalidOperationException ex) when (ex.Message.Contains("does not consist of triangles"))
{
// identify and fix/regenerate the offending convex hull collider
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- gameSettings
- Duplicate collider added
- Trying to remove unregistered collider
- [ ] cannot be null in
- [ . ] must be in
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/c6b050c207f71e80.
Report an issue: GitHub.
Appendix: source
Thrown at sources/engine/Stride.Navigation/NavigationMeshBuilder.cs:529
Plane plane = new Plane(planeDesc.Normal, planeDesc.Offset)
{
// Pre-Transform plane parameters
Normal = Vector3.TransformNormal(planeDesc.Normal, transform)
};
plane.Normal.Normalize();
plane.D += Vector3.Dot(transform.TranslationVector, plane.Normal);
colliderData.Planes.Add(plane);
}
else if (shapeType == typeof(ConvexHullColliderShape))
{
var hull = (ConvexHullColliderShape)shape;
Matrix transform = hull.PositiveCenterMatrix * entityWorldMatrix;
// V-HACD emits hull triangles in left-handed winding, matching the navmesh input convention.
int[] indices = new int[hull.Indices.Count];
if (hull.Indices.Count % 3 != 0) throw new InvalidOperationException($"{shapeType} does not consist of triangles");
for (int i = 0; i < hull.Indices.Count; i++)
{
indices[i] = (int)hull.Indices[i];
}
entityNavigationMeshInputBuilder.AppendArrays(hull.Points.ToArray(), indices, transform);
}
else if (shapeType == typeof(StaticMeshColliderShape))
{
var mesh = (StaticMeshColliderShape)shape;
Matrix transform = mesh.PositiveCenterMatrix * entityWorldMatrix;
mesh.GetMeshDataCopy(out var verts, out var indices);
// Convert hull indices to int
if (indices.Length % 3 != 0) throw new InvalidOperationException($"{shapeType} does not consist of triangles");
for (int i = 0; i < indices.Length; i += 3)
{View on GitHub (pinned to 96fad776d2)