stride3d/stride · error · InvalidOperationException
Invalid GeometricPrimitive
Error message
Invalid GeometricPrimitive [{0}]. Expecting non-zero Vertices array What it means
PrimitiveProceduralModelBase.Generate builds the mesh via CreatePrimitiveMeshData and requires at least one vertex. If the produced GeometricMeshData has an empty Vertices array the primitive type failed to produce geometry, so InvalidOperationException is thrown.
Solutions
- Fix or initialize the primitive Type so CreatePrimitiveMeshData returns real geometry
- Check custom CreatePrimitiveMeshData overrides to ensure they populate Vertices
- Validate primitive parameters (slices, tessellation, scale) are non-degenerate before generating
Example fix
// before
public override GeometricMeshData<VertexPositionNormalTexture> CreatePrimitiveMeshData()
=> _cachedData; // may be empty
// after
public override GeometricMeshData<VertexPositionNormalTexture> CreatePrimitiveMeshData()
{
var data = _cachedData ?? BuildSphere(tessellation);
if (data.Vertices.Length == 0)
data = BuildSphere(DefaultTessellation); // fall back to valid geometry
return data;
} Defensive patterns
Strategy: validation
Validate before calling
var data = primitive.CreatePrimitiveMeshData();
if (data == null || data.Vertices == null || data.Vertices.Length == 0)
throw new InvalidOperationException("Primitive produced no vertices; check Type and parameters"); Try / catch
try { descriptor.Type.Generate(services, model); }
catch (InvalidOperationException ex) when (ex.Message.Contains("non-zero Vertices")) {
logger.Error($"Primitive {descriptor.Type} generated an empty mesh");
} Prevention
- Validate primitive parameters (tessellation, radius, scale) before generating
- Test custom IProceduralModel implementations with unit checks on vertex counts
- Never return cached-but-uninitialized mesh data
When it happens
Trigger: A derived procedural model (Type property) whose CreatePrimitiveMeshData returns an empty vertex array — e.g. a primitive type not yet initialized, a custom primitive with zero parameters, or a type whose mesh generation silently produced nothing.
Common situations: ProceduralModelDescriptor with a custom IProceduralModel implementation returning empty data; uninitialized primitive Type field; degenerate parameters (e.g. zero tessellation) causing no vertices.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- Cannot generate more than 65535 indices on feature level HW…
- Invalid GeometricPrimitive
- A texture with size [ ] already exist with the same output…
- Asked for " + i + " but no more than 10 default textures…
- Begin must be called before functionName
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/bf1a5b1b0fdcb559.
Report an issue: GitHub.
Appendix: source
Thrown at sources/engine/Stride.Rendering/Rendering/ProceduralModels/PrimitiveProceduralModelBase.cs:103
}
public void Generate(IServiceRegistry services, Model model)
{
ArgumentNullException.ThrowIfNull(model);
var needsTempDevice = false;
var graphicsDevice = services?.GetSafeServiceAs<IGraphicsDeviceService>().GraphicsDevice;
if (graphicsDevice == null)
{
graphicsDevice = GraphicsDevice.New();
needsTempDevice = true;
}
var data = CreatePrimitiveMeshData();
if (data.Vertices.Length == 0)
{
throw new InvalidOperationException("Invalid GeometricPrimitive [{0}]. Expecting non-zero Vertices array");
}
if (LocalOffset != Vector3.Zero)
{
for (var index = 0; index < data.Vertices.Length; index++)
{
data.Vertices[index].Position += LocalOffset;
}
}
//Scale if necessary
if (Scale != Vector3.One)
{
var inverseMatrix = Matrix.Scaling(Scale);
inverseMatrix.Invert();
for (var index = 0; index < data.Vertices.Length; index++)
{
data.Vertices[index].Position *= Scale;View on GitHub (pinned to 96fad776d2)