BabylonJS/Babylon.js · error · Error

Draco: Cannot encode geometry with no vertices.

Error message

Draco: Cannot encode geometry with no vertices.

What it means

DracoEncoder.encodeMeshAsync throws when `input.getTotalVertices()` is 0 — Draco encodes vertex data, and a mesh/geometry with no vertices cannot be encoded. The check happens before any attribute preparation.

Source

Thrown at packages/dev/core/src/Meshes/Compression/dracoEncoder.ts:272

        if (this._modulePromise) {
            const encoder = await this._modulePromise;
            return EncodeMesh(encoder.module, attributes, indices, mergedOptions);
        }

        throw new Error("Draco: Encoder module is not available");
    }

    /**
     * Encodes a mesh or geometry into a Draco-encoded mesh data.
     * @param input the mesh or geometry to encode
     * @param options options for the encoding
     * @returns a promise that resolves to the newly-encoded data
     */
    public async encodeMeshAsync(input: Mesh | Geometry, options?: IDracoEncoderOptions): Promise<IDracoEncodedMeshData> {
        const verticesCount = input.getTotalVertices();
        if (verticesCount == 0) {
            throw new Error("Draco: Cannot encode geometry with no vertices.");
        }

        // Prepare parameters for encoding
        if (input instanceof Mesh && input.morphTargetManager && options?.method === "MESH_EDGEBREAKER_ENCODING") {
            Logger.Warn("Draco: Cannot use EDGEBREAKER encoding method with morph targets. Falling back to SEQUENTIAL method.");
            options.method = "MESH_SEQUENTIAL_ENCODING";
        }

        const indices = PrepareIndicesForDraco(input);
        const attributes = PrepareAttributesForDraco(input, options?.excludedAttributes);

        return await this._encodeAsync(attributes, indices, options);
    }
}

View on GitHub (pinned to 0592b347b8)

Solutions

  1. Check `mesh.getTotalVertices() > 0` before encoding and skip empty meshes.
  2. Ensure the mesh actually has geometry assigned before encoding (create/attach vertex data first).
  3. For batch pipelines, filter the list: `meshes.filter(m => m.getTotalVertices() > 0)`.
  4. If geometry was released, re-load or re-assign the vertex data before encoding.

Example fix

// before
for (const mesh of meshes) {
    await encoder.encodeMeshAsync(mesh);
}

// after
for (const mesh of meshes) {
    if (mesh.getTotalVertices() === 0) continue;
    await encoder.encodeMeshAsync(mesh);
}
Defensive patterns

Strategy: validation

Validate before calling

if (input.getTotalVertices() === 0) {
    return null; // skip empty meshes
}
return await encoder.encodeMeshAsync(input, options);

Type guard

function isEncodableDracoInput(input: Mesh | Geometry): boolean {
    return input.getTotalVertices() > 0;
}

Try / catch

try {
    return await encoder.encodeMeshAsync(mesh);
} catch (e) {
    if (e instanceof Error && e.message.includes("no vertices")) {
        Logger.Warn(`Skipping empty mesh ${mesh.name}`);
        return null;
    }
    throw e;
}

Prevention

When it happens

Trigger: Calling `encodeMeshAsync` on an empty Mesh (never given geometry), a disposed mesh, a Geometry with no vertex buffer, or a mesh whose vertex data was released (e.g. after `mesh.geometry.releaseVertexArray...` or `freeze`+free memory patterns).

Common situations: Batch-encoding many meshes where some are empty placeholders; encoding a mesh before `CreateMesh`/vertex data assignment; procedural meshes that failed to build; assets where all meshes LOD0 is empty.

Related errors


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