BabylonJS/Babylon.js · error

No valid mesh was provided for mesh or convex hull shape par

Error message

No valid mesh was provided for mesh or convex hull shape parameter. Please provide a mesh with valid geometry (number of vertices greater than 0).

What it means

PhysicsAggregate._addSizeOptions resolves shape sizing inputs from the constructor options. For MESH, CONVEX_HULL, and HEIGHTFIELD types it needs an actual mesh with vertex data: it takes options.mesh if given, otherwise falls back to the transformNode itself when that node has vertices. If neither is usable (no mesh, or mesh with 0 vertices), it throws because the shape would have no geometry to build from.

Source

Thrown at packages/dev/core/src/Physics/v2/physicsAggregate.ts:247

                    this._options.pointA = this._options.pointA ?? new Vector3(0, min.y + capRadius, 0);
                    this._options.pointB = this._options.pointB ?? new Vector3(0, min.y + extents.y - capRadius, 0);
                }
                break;
            case PhysicsShapeType.CYLINDER:
                {
                    const capRadius = extents.x / 2;
                    this._options.radius = this._options.radius ?? capRadius;
                    this._options.pointA = this._options.pointA ?? new Vector3(0, min.y, 0);
                    this._options.pointB = this._options.pointB ?? new Vector3(0, min.y + extents.y, 0);
                }
                break;
            case PhysicsShapeType.MESH:
            case PhysicsShapeType.CONVEX_HULL:
            case PhysicsShapeType.HEIGHTFIELD:
                if (!this._options.mesh && this._hasVertices(this.transformNode)) {
                    this._options.mesh = this.transformNode as Mesh;
                } else if (!this._options.mesh || !this._hasVertices(this._options.mesh)) {
                    throw new Error(
                        "No valid mesh was provided for mesh or convex hull shape parameter. Please provide a mesh with valid geometry (number of vertices greater than 0)."
                    );
                }
                break;
            case PhysicsShapeType.BOX:
                this._options.extents = this._options.extents ?? new Vector3(extents.x, extents.y, extents.z);
                this._options.rotation = this._options.rotation ?? Quaternion.Identity();
                break;
        }
    }

    /**
     * Releases the body, shape and material
     */
    public dispose(): void {
        if (this._nodeDisposeObserver) {
            this.body.transformNode.onDisposeObservable.remove(this._nodeDisposeObserver);
            this._nodeDisposeObserver = null;

View on GitHub (pinned to 0592b347b8)

Solutions

  1. Pass an explicit mesh with geometry: new PhysicsAggregate(node, type, { mesh: sourceMesh, ... }, scene).
  2. Wait for the mesh to finish loading/importing (await ImportMeshAsync / onMeshReady) so vertices exist, then create the aggregate.
  3. Use a sizing-based shape (BOX, SPHERE, CAPSULE) if you only need approximate collision and have no mesh.
  4. Check node.getTotalVertices() > 0 before constructing; also ensure the node is a Mesh, not a bare TransformNode.

Example fix

// before
const aggregate = new PhysicsAggregate(emptyNode, PhysicsShapeType.CONVEX_HULL, { mass: 1 }, scene);
// after
await SceneLoader.ImportMeshAsync("", "assets/", "rock.glb", scene);
if (rock.getTotalVertices() > 0) {
  const aggregate = new PhysicsAggregate(rock, PhysicsShapeType.CONVEX_HULL, { mass: 1, mesh: rock }, scene);
}
Defensive patterns

Strategy: validation

Validate before calling

if (!(node instanceof Mesh) || node.getTotalVertices() === 0) {
  throw new Error("PhysicsAggregate with MESH/CONVEX_HULL/HEIGHTFIELD requires a Mesh with vertices");
}
const aggregate = new PhysicsAggregate(node, PhysicsShapeType.CONVEX_HULL, { mass: 1, mesh: node }, scene);

Type guard

function hasVertices(n: TransformNode | AbstractMesh): n is Mesh {
  return n instanceof Mesh && n.getTotalVertices() > 0;
}

Try / catch

try {
  const aggregate = new PhysicsAggregate(node, PhysicsShapeType.CONVEX_HULL, { mass: 1 }, scene);
} catch (e) {
  if ((e as Error).message.includes("No valid mesh")) {
    console.error("Provide a loaded Mesh with vertices or use a BOX/SPHERE shape instead", e);
  }
  throw e;
}

Prevention

When it happens

Trigger: new PhysicsAggregate(node, PhysicsShapeType.MESH, options, scene) where options.mesh is null and node is a bare TransformNode or an empty Mesh (getTotalVertices() === 0), i.e. the else-if at physicsAggregate.ts:247.

Common situations: Attaching a mesh physics shape to a plain TransformNode or camera; creating the aggregate before the mesh's vertices load (async glTF import not awaited); instanced/thin instances where the source mesh has no vertices; passing a GUI or particle object instead of a Mesh.

Related errors


AI-assisted analysis of BabylonJS/Babylon.js@0592b347b8 (2026-08-30). Data as JSON: /api/errors/b5a3feb968a7751e. Report an issue: GitHub.