BabylonJS/Babylon.js · error
Unable to build a mesh. Manifold has 0 vertex
Error message
Unable to build a mesh. Manifold has 0 vertex
What it means
toMesh rebuilds a Babylon Mesh from the CSG2's vertex data; if the resulting Manifold contains zero vertices (e.g. an empty result geometry), it throws because a mesh cannot be built from empty vertex data. This guards against producing degenerate, invisible meshes from a CSG operation.
Source
Thrown at packages/dev/core/src/Meshes/csg2.ts:233
* @returns a new Mesh
*/
public toMesh(name: string, scene?: Scene, options?: Partial<IMeshRebuildOptions>): Mesh {
const localOptions = {
rebuildNormals: false,
centerMesh: true,
...options,
};
const vertexData = this.toVertexData({ rebuildNormals: localOptions.rebuildNormals });
const normalComponent = this._vertexStructure.find((c) => c.kind === VertexBuffer.NormalKind);
const manifoldMesh: IManifoldMesh = this._manifold.getMesh(localOptions.rebuildNormals && normalComponent ? [3, 4, 5] : undefined);
const vertexCount = manifoldMesh.vertProperties.length / manifoldMesh.numProp;
// Rebuild mesh from vertex data
const output = new Mesh(name, scene);
vertexData.applyToMesh(output);
if (!vertexCount) {
throw new Error("Unable to build a mesh. Manifold has 0 vertex");
}
// Center mesh
if (localOptions.centerMesh) {
const extents = output.getBoundingInfo().boundingSphere.center;
output.position.set(-extents.x, -extents.y, -extents.z);
output.bakeCurrentTransformIntoVertices();
}
// Submeshes
let id = manifoldMesh.runOriginalID[0];
let start = manifoldMesh.runIndex[0];
let materialIndex = 0;
const materials: Material[] = [];
scene = output.getScene();
for (let run = 0; run < manifoldMesh.numRun; ++run) {
const nextID = manifoldMesh.runOriginalID[run + 1];
if (nextID !== id) {
View on GitHub (pinned to 0592b347b8)
Solutions
- Verify the operands actually overlap before the boolean operation
- Check the CSG result (vertex/vertexCount) for emptiness and fall back to the original mesh
- Fix the source mesh so it contains geometry (non-zero vertex count) before converting
Example fix
// before
const result = a.subtract(b).toMesh('diff', scene); // may be empty
// after
const c = a.subtract(b);
if (c.getCVertices?.() ?? true) { /* check non-empty */ }
const result = c.toMesh('diff', scene); Defensive patterns
Strategy: validation
Validate before calling
const result = a.intersect(b);
// guard against empty boolean result before toMesh
if (!result) throw new Error('CSG result is empty'); Type guard
const nonEmpty = (c: CSG2): boolean => { try { return !!c; } catch { return false; } }; Try / catch
try {
mesh = result.toMesh(name, scene);
} catch (e) {
if (String(e).includes('0 vertex')) { mesh = fallbackOriginalMesh(); }
else throw e;
} Prevention
- Check operand bounding boxes overlap before boolean ops
- Avoid subtracting a body that fully contains the target
- Ensure source meshes have non-zero vertex counts before CSG2.FromMesh
When it happens
Trigger: Calling csg.toMesh() after an operation whose result was empty — subtracting a mesh that fully contains the other, intersecting disjoint solids, or building the CSG from an empty/invalid mesh.
Common situations: Boolean ops between non-overlapping objects; a subtract where the tool body completely swallows the target; importing meshes that failed to produce geometry.
Related errors
- CSG must be used with geometries having the same number of p
- Error while creating the CSG:
- Unable to get nav mesh. No vertices or indices.
- Draco: Cannot decode invalid geometry type ${type}
- The vertexData must at least have positions and indices
AI-assisted analysis of BabylonJS/Babylon.js@0592b347b8 (2026-08-30).
Data as JSON: /api/errors/06a9ac8cfe04f0e3.
Report an issue: GitHub.