BabylonJS/Babylon.js · error

Cannot get the last selected variant on a glTF mesh that doe

Error message

Cannot get the last selected variant on a glTF mesh that does not have the ${NAME} extension

What it means

KHR_materials_variants stores per-variant mesh data in the node's extension metadata. GetLastSelectedVariant reads the metadata's 'lastSelected' record from the root TransformNode. If the mesh was never loaded with the KHR_materials_variants extension (or the wrong node is passed), there is no metadata and Babylon throws this error instead of returning a misleading null.

Source

Thrown at packages/dev/loaders/src/glTF/2.0/Extensions/KHR_materials_variants.pure.ts:167

    }

    /**
     * Reset back to the original before selecting a variant.
     * @param rootNode The glTF root node
     */
    public reset(rootNode: TransformNode): void {
        KHR_materials_variants.Reset(rootNode);
    }

    /**
     * Gets the last selected variant name(s) or null if original.
     * @param rootNode The glTF root node
     * @returns The selected variant name(s).
     */
    public static GetLastSelectedVariant(rootNode: TransformNode): Nullable<string | string[]> {
        const extensionMetadata = this._GetExtensionMetadata(rootNode);
        if (!extensionMetadata) {
            throw new Error(`Cannot get the last selected variant on a glTF mesh that does not have the ${NAME} extension`);
        }

        return extensionMetadata.lastSelected;
    }

    /**
     * Gets the last selected variant name(s) or null if original.
     * @param rootNode The glTF root node
     * @returns The selected variant name(s).
     */
    public getLastSelectedVariant(rootNode: TransformNode): Nullable<string | string[]> {
        return KHR_materials_variants.GetLastSelectedVariant(rootNode);
    }

    private static _GetExtensionMetadata(rootNode: Nullable<TransformNode>): Nullable<IExtensionMetadata> {
        return rootNode?._internalMetadata?.gltf?.[NAME] || null;
    }

View on GitHub (pinned to 0592b347b8)

Solutions

  1. Pass the glTF root TransformNode returned by SceneLoader.ImportMesh/LoadAssetContainerAsync, not a child mesh.
  2. Verify the .gltf/.glb file actually declares KHR_materials_variants in extensionsUsed.
  3. Check GetExtensionMetadata (or node.metadata.gltfExtensions) for the extension before calling the API; fall back to selecting variants via the loader's promises otherwise.

Example fix

// before
const variant = KHRMaterialExtensions.GetLastSelectedVariant(anyMesh);
// after
const variant = KHRMaterialExtensions.GetLastSelectedVariant(rootNodes[0]); // actual glTF root with variant metadata
Defensive patterns

Strategy: validation

Validate before calling

const meta = KHRMaterialExtensions.GetExtensionMetadata(rootNode);
if (!meta || !meta.variants) throw new Error('Asset does not use KHR_materials_variants');

Type guard

function hasVariantMetadata(node: TransformNode): boolean {
  return !!(node.metadata as any)?.gltf?.extensions?.['KHR_materials_variants'];
}

Prevention

When it happens

Trigger: CallingKHRMaterialExtensions.GetLastSelectedVariant(rootNode) on a TransformNode whose metadata lacks the extension's metadata entry — e.g. the glTF asset never declared the KHR_materials_variants extension, or the node passed is not the glTF root node created by the loader.

Common situations: Passing a child mesh or an unrelated TransformNode instead of the root node returned by the loader; loading a model that uses other KHR extensions but not materials_variants; constructing meshes procedurally and assuming variant APIs exist.

Related errors


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