{"record":{"id":"e9d896b33be64b1f","repo":"BabylonJS/Babylon.js","slug":"failed-to-decode-the-ktx2-file-layer-mipmap-lay-e9d896","errorCode":null,"errorMessage":"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}.","messagePattern":"Failed to decode the KTX2 file: layer (.+?) of the base mip level is (.+?)x(.+?) but layer 0 is (.+?)x(.+?)\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/dev/core/src/Materials/Textures/rawTexture2DArray.functions.ts","lineNumber":183,"sourceCode":"    // the first layerCount entries and its layers are already in ascending order.\r\n    const baseLevel = decodedData.mipmaps.slice(0, layerCount);\r\n\r\n    if (baseLevel.length !== layerCount) {\r\n        throw new Error(`Failed to decode the KTX2 file: expected ${layerCount} layers for the base mip level but got ${baseLevel.length}.`);\r\n    }\r\n\r\n    // Every layer of a level shares the level's dimensions, and forceRGBA above means each one must be exactly\r\n    // width * height * 4 bytes. RawTexture2DArray takes all the layers as one flat buffer and cannot detect a\r\n    // short or mismatched layer, so validate here rather than uploading malformed data.\r\n    const { width, height } = baseLevel[0];\r\n    const expectedLayerByteLength = width * height * 4;\r\n\r\n    for (const mipmap of baseLevel) {\r\n        if (!mipmap.data) {\r\n            throw new Error(`Failed to decode the KTX2 file: layer ${mipmap.layerIndex} of the base mip level is empty.`);\r\n        }\r\n        if (mipmap.width !== width || mipmap.height !== height) {\r\n            throw new Error(\r\n                `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}.`\r\n            );\r\n        }\r\n        if (mipmap.data.byteLength !== expectedLayerByteLength) {\r\n            throw new Error(\r\n                `Failed to decode the KTX2 file: layer ${mipmap.layerIndex} of the base mip level holds ${mipmap.data.byteLength} bytes but ${expectedLayerByteLength} were expected.`\r\n            );\r\n        }\r\n    }\r\n\r\n    // A 2D array texture is uploaded as a single buffer holding every layer back to back.\r\n    const textureData = new Uint8Array(expectedLayerByteLength * layerCount);\r\n    let byteOffset = 0;\r\n    for (const mipmap of baseLevel) {\r\n        textureData.set(mipmap.data!, byteOffset);\r\n        byteOffset += mipmap.data!.byteLength;\r\n    }\r\n\r","sourceCodeStart":165,"sourceCodeEnd":201,"githubUrl":"https://github.com/BabylonJS/Babylon.js/blob/0592b347b8a4ee0236089ea86a749cacfdb266d8/packages/dev/core/src/Materials/Textures/rawTexture2DArray.functions.ts#L165-L201","documentation":"All layers of a KTX2 2D array texture's base mip must have identical dimensions, since they are uploaded as one array texture. This error is thrown when a decoded layer's width/height differs from layer 0.","triggerScenarios":"Calling CreateTexture2DArrayFromKTX2Async with a KTX2 file whose array layers were encoded with inconsistent dimensions at the base mip level.","commonSituations":"Hand-assembled KTX2 arrays where slices of different resolutions were combined, broken exporter scripts, image sets generated at mixed resolutions before packing.","solutions":["Re-encode the KTX2 array ensuring every source image is resized to the same width/height before packing.","Verify the exporter/pipeline output dimensions with a KTX2 inspector (e.g. toktx --basetype or ktxinfo).","If layers must differ, use separate textures or render them per-frame instead of a 2D array texture."],"exampleFix":"// before: packing mixed-resolution sources\nawait packKtx2([imgA_512, imgB_256]);\n// after: normalize sizes first\nconst normalized = sources.map(img => resize(img, 512, 512));\nawait packKtx2(normalized);","handlingStrategy":"validation","validationCode":"// Check source images share dimensions before packing a KTX2 array\nfor (const img of layers) {\n  if (img.width !== layers[0].width || img.height !== layers[0].height) {\n    throw new Error(`Layer ${img.name} is ${img.width}x${img.height}, expected ${layers[0].width}x${layers[0].height}`);\n  }\n}","typeGuard":"function allSameSize(images: { width: number; height: number }[]): boolean {\n  return images.every(i => i.width === images[0].width && i.height === images[0].height);\n}","tryCatchPattern":"try {\n  const tex = await CreateTexture2DArrayFromKTX2Async(url, scene);\n} catch (e) {\n  if (String(e.message).includes(\"base mip level is\")) {\n    console.error(\"KTX2 layers have inconsistent dimensions — re-export asset.\");\n  }\n}","preventionTips":["Normalize all source images to one resolution in the asset pipeline before KTX2 packing.","Inspect packed KTX2 files (ktxinfo/toktx) as a build step.","Never hand-assemble KTX2 arrays from mixed-resolution sources."],"tags":["ktx2","texture-array","dimension-mismatch","asset-validation"],"backgroundTag":"ktx2-layer-dimension-mismatch","analyzedSha":"0592b347b8a4ee0236089ea86a749cacfdb266d8","analyzedAt":"2026-08-30T15:11:20.442Z","schemaVersion":2},"datasetVersion":"2026-08-30T18:17:15.746Z"}