BabylonJS/Babylon.js · error · Error

${context}: Unsupported mode ${primitive.mode}

Error message

${context}: Unsupported mode ${primitive.mode}

What it means

KHR_draco_mesh_compression only supports triangle-based primitive modes (TRIANGLES=4 and TRIANGLE_STRIP=5). _loadVertexDataAsync throws this when the primitive's mode is any other value (points, lines, etc.), because the Draco decoder produces triangle geometry only.

Source

Thrown at packages/dev/loaders/src/glTF/2.0/Extensions/KHR_draco_mesh_compression.pure.ts:69

        this._loader = loader;
        this.enabled = DracoDecoder.DefaultAvailable && this._loader.isExtensionUsed(NAME);
    }

    /** @internal */
    public dispose(): void {
        delete this.dracoDecoder;
        (this._loader as any) = null;
    }

    /**
     * @internal
     */
    // eslint-disable-next-line no-restricted-syntax
    public _loadVertexDataAsync(context: string, primitive: IMeshPrimitive, babylonMesh: Mesh): Nullable<Promise<Geometry>> {
        return GLTFLoader.LoadExtensionAsync<IKHRDracoMeshCompression, Geometry>(context, primitive, this.name, async (extensionContext, extension) => {
            if (primitive.mode != undefined) {
                if (primitive.mode !== MeshPrimitiveMode.TRIANGLES && primitive.mode !== MeshPrimitiveMode.TRIANGLE_STRIP) {
                    throw new Error(`${context}: Unsupported mode ${primitive.mode}`);
                }
            }

            const attributes: { [kind: string]: number } = {};
            const normalized: { [kind: string]: boolean } = {};
            const loadAttribute = (name: string, kind: string) => {
                const uniqueId = extension.attributes[name];
                if (uniqueId == undefined) {
                    return;
                }

                babylonMesh._delayInfo = babylonMesh._delayInfo || [];
                if (babylonMesh._delayInfo.indexOf(kind) === -1) {
                    babylonMesh._delayInfo.push(kind);
                }

                attributes[kind] = uniqueId;

View on GitHub (pinned to 0592b347b8)

Solutions

  1. Convert the primitive to TRIANGLES (or TRIANGLE_STRIP) in the asset, or remove Draco compression from non-triangle primitives
  2. Re-export with the DCC tool configured to not compress non-triangle primitives
  3. Split line/point geometry into separate non-Draco primitives/meshes
  4. Use glTF-Validator to flag mode/extension incompatibilities before loading

Example fix

// before
"primitives": [{ "mode": 1, "extensions": { "KHR_draco_mesh_compression": {...} } }]
// after
"primitives": [{ "mode": 4, "extensions": { "KHR_draco_mesh_compression": {...} } }]
Defensive patterns

Strategy: validation

Validate before calling

for (const mesh of asset.meshes ?? []) {
  for (const prim of mesh.primitives) {
    if (prim.extensions?.KHR_draco_mesh_compression && ![4, 5].includes(prim.mode ?? 4)) {
      throw new Error(`Draco primitive with unsupported mode ${prim.mode}`);
    }
  }
}

Type guard

function isTriangleMode(mode: number | undefined): boolean {
  return mode === undefined || mode === 4 || mode === 5;
}

Try / catch

try {
  await BABYLON.SceneLoader.LoadAsync('./', 'model.glb', engine);
} catch (e) {
  if (e instanceof Error && e.message.includes('Unsupported mode')) {
    console.error('Draco primitive uses non-triangle mode; fix asset or drop Draco');
  } else throw e;
}

Prevention

When it happens

Trigger: Loading a glTF primitive with mode 0 (POINTS), 1 (LINES), 2 (LINE_LOOP), 3 (LINE_STRIP), or 6 (TRIANGLE_FAN) that also uses KHR_draco_mesh_compression.

Common situations: Exporters that Draco-compress all primitives regardless of mode; hand-toggled extensions on line/point primitives; assets combining wireframe/line geometry with Draco compression.

Related errors


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