BabylonJS/Babylon.js · error · Error
Failed to decode the KTX2 file: layer ${mipmap.layerIndex} o
Error message
Failed to decode the KTX2 file: layer ${mipmap.layerIndex} of the base mip level holds ${mipmap.data.byteLength} bytes but ${expectedLayerByteLength} were expected. What it means
Each layer of the base mip level must contain exactly width*height*4 bytes (RGBA8 uncompressed). This error is thrown when a decoded layer's byte length does not match the expected size, indicating the decoder produced data in an unexpected format or size.
Source
Thrown at packages/dev/core/src/Materials/Textures/rawTexture2DArray.functions.ts:188
}
// Every layer of a level shares the level's dimensions, and forceRGBA above means each one must be exactly
// width * height * 4 bytes. RawTexture2DArray takes all the layers as one flat buffer and cannot detect a
// short or mismatched layer, so validate here rather than uploading malformed data.
const { width, height } = baseLevel[0];
const expectedLayerByteLength = width * height * 4;
for (const mipmap of baseLevel) {
if (!mipmap.data) {
throw new Error(`Failed to decode the KTX2 file: layer ${mipmap.layerIndex} of the base mip level is empty.`);
}
if (mipmap.width !== width || mipmap.height !== height) {
throw new Error(
`Failed to decode the KTX2 file: layer ${mipmap.layerIndex} of the base mip level is ${mipmap.width}x${mipmap.height} but layer 0 is ${width}x${height}.`
);
}
if (mipmap.data.byteLength !== expectedLayerByteLength) {
throw new Error(
`Failed to decode the KTX2 file: layer ${mipmap.layerIndex} of the base mip level holds ${mipmap.data.byteLength} bytes but ${expectedLayerByteLength} were expected.`
);
}
}
// A 2D array texture is uploaded as a single buffer holding every layer back to back.
const textureData = new Uint8Array(expectedLayerByteLength * layerCount);
let byteOffset = 0;
for (const mipmap of baseLevel) {
textureData.set(mipmap.data!, byteOffset);
byteOffset += mipmap.data!.byteLength;
}
return new RawTexture2DArray(
textureData,
width,
height,
layerCount,
View on GitHub (pinned to 0592b347b8)
Solutions
- Ensure the KTX2/basis transcoder WASM files match your @babylonjs/core version (same release line).
- Re-export the KTX2 file without unusual supercompression or with a supported output format.
- Verify the file is not truncated or corrupted (checksum against the original export).
- Update @babylonjs/core to the latest patch where this decode path may be fixed.
Example fix
// before: mismatched transcoder assets
engine._loadFile("old_basis_encoder/basis_transcoder.js");
// after: load the transcoder matching the core version
await scene.getEngine()._ktx2Decoder.initializeAsync(matchingTranscoderUrl); Defensive patterns
Strategy: validation
Validate before calling
// Ensure layer byte length matches RGBA8 expectation after decode
const expected = width * height * 4;
if (layerData.byteLength !== expected) {
throw new Error(`Layer holds ${layerData.byteLength} bytes, expected ${expected}`);
} Type guard
function isExpectedLayerBytes(m: { data: ArrayBuffer | null; width: number; height: number }): boolean {
return m.data != null && m.data.byteLength === m.width * m.height * 4;
} Try / catch
try {
const tex = await CreateTexture2DArrayFromKTX2Async(url, scene);
} catch (e) {
if (String(e.message).includes("were expected")) {
console.error("Transcoder output format mismatch — check transcoder WASM version.");
}
} Prevention
- Load the KTX2 transcoder from the same Babylon.js release as your core package.
- Pin transcoder asset versions in deployment (no floating 'latest').
- Add asset checksums to CI to catch corruption early.
When it happens
Trigger: Calling CreateTexture2DArrayFromKTX2Async where the transcoded base-level layer data byte length differs from width*height*4 — e.g. mismatched transcoder output format, partially decoded layer, or corrupt file.
Common situations: Version mismatch between the Babylon.js core and the loaded basis/KTX2 transcoder WASM, misconfigured transcoder formats (e.g. requesting a compressed output the array path doesn't expect), corrupted assets.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Failed to decode the KTX2 file. ${decodedData.errors}
- Failed to decode the KTX2 file: expected ${layerCount} layer
- Failed to decode the KTX2 file: layer ${mipmap.layerIndex} o
- Failed to decode the KTX2 file: layer ${mipmap.layerIndex} o
- Failed to fetch KTX2 file "${data}": ${response.status} ${re
AI-assisted analysis of BabylonJS/Babylon.js@0592b347b8 (2026-08-30).
Data as JSON: /api/errors/d1b173d31e5dc580.
Report an issue: GitHub.