BabylonJS/Babylon.js · error · Error

EXR data could not be decoded.

Error message

EXR data could not be decoded.

What it means

_getCubeMapTextureDataAsync decodes an EXR panorama buffer with ReadExrDataAsync and then converts it to a cubemap. If decoding produces no pixel data (exrData.data is falsy), the library throws rather than passing garbage into PanoramaToCubeMapTools.

Source

Thrown at packages/dev/core/src/Materials/Textures/exrCubeTexture.pure.ts:67

    /**
     * Get the current class name of the texture useful for serialization or dynamic coding.
     * @returns "EXRCubeTexture"
     */
    public override getClassName(): string {
        return "EXRCubeTexture";
    }

    /**
     * Convert the raw data from the server into cubemap faces
     * @param buffer The buffer containing the texture data
     * @param size The cubemap face size
     * @param supersample Defines if texture must be supersampled
     * @returns The cube map data
     */
    protected async _getCubeMapTextureDataAsync(buffer: ArrayBuffer, size: number, supersample: boolean): Promise<CubeMapInfo> {
        const exrData = await ReadExrDataAsync(buffer);
        if (!exrData.data) {
            throw new Error("EXR data could not be decoded.");
        }

        const cubeMapData = PanoramaToCubeMapTools.ConvertPanoramaToCubemap(exrData.data, exrData.width, exrData.height, size, supersample, false);
        return cubeMapData;
    }

    protected _instantiateClone(): this {
        return new EXRCubeTexture(this.url, this.getScene() || this._getEngine()!, this._size, this._noMipmap, this._generateHarmonics, this.gammaSpace) as this;
    }

    /**
     * Serialize the texture to a JSON representation.
     * @returns The JSON representation of the texture
     */
    public override serialize(): any {
        const serializationObject = super.serialize();
        if (!serializationObject) {
            return null;

View on GitHub (pinned to 0592b347b8)

Solutions

  1. Verify the URL actually serves a valid EXR file (check magic bytes 0x76 0x2f 0x31 0x01)
  2. Re-download or re-export the EXR file, e.g. from Blender/3ds Max with standard (non-exotic) compression
  3. Check that the server is not returning an error page with a 200 status
  4. Try a known-good EXR to isolate file vs code
Defensive patterns

Strategy: try-catch

Validate before calling

async function isExr(url) {
  const buf = new Uint8Array(await (await fetch(url)).arrayBuffer());
  return buf[0] === 0x76 && buf[1] === 0x2f && buf[2] === 0x31 && buf[3] === 0x01;
}

Type guard

function looksLikeExr(b: Uint8Array): boolean {
  return b.length > 4 && b[0] === 0x76 && b[1] === 0x2f && b[2] === 0x31 && b[3] === 0x01;
}

Try / catch

try {
  const tex = new EXRCubeTexture(url, scene, 128);
} catch (e) {
  if (e instanceof Error && e.message.includes("EXR data could not be decoded")) {
    console.error(`Invalid EXR at ${url}, falling back`);
    tex = fallbackTexture;
  } else throw e;
}

Prevention

When it happens

Trigger: Calling new EXRCubeTexture(url, scene, ...) where the downloaded buffer is not a decodable EXR file (corrupt file, truncated download, wrong file served, or an EXR variant the decoder does not support).

Common situations: Server returns an HTML error page or JSON with 200 status instead of EXR data, file saved with .exr extension but is actually a different format, or an unsupported EXR compression method.

Related errors


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