BabylonJS/Babylon.js · error · Error

EXRLoader.parse: file contains unsupported data channels.

Error message

EXRLoader.parse: file contains unsupported data channels.

What it means

After scanning the header's channel list, the decoder must find R, G, B, A or Y to decode. If the file's only recognized channels are none of these (e.g. only Z/depth, custom AOV channels, or channels whose names the switch ignores), it throws because it cannot map any channel to output pixels.

Source

Thrown at packages/dev/core/src/Materials/Textures/Loaders/EXR/exrLoader.decoder.ts:199

    if (channels.R && channels.G && channels.B && channels.A) {
        decoder.outputChannels = 4;
        decoder.decodeChannels = { R: 0, G: 1, B: 2, A: 3 };
    } else if (channels.R && channels.G && channels.B) {
        fillAlpha = true;
        decoder.outputChannels = 4;
        decoder.decodeChannels = { R: 0, G: 1, B: 2, A: 3 };
    } else if (channels.R && channels.G) {
        decoder.outputChannels = 2;
        decoder.decodeChannels = { R: 0, G: 1 };
    } else if (channels.R) {
        decoder.outputChannels = 1;
        decoder.decodeChannels = { R: 0 };
    } else if (channels.Y) {
        decoder.outputChannels = 1;
        decoder.decodeChannels = { Y: 0 };
        // Note: Supporting 'Y' channel for legacy compatibility; prefer 'R' in new EXRs.
    } else {
        throw new Error("EXRLoader.parse: file contains unsupported data channels.");
    }

    if (decoder.type === 1) {
        // half
        switch (outputType) {
            case EXROutputType.Float:
                decoder.getter = ParseFloat16;
                decoder.inputSize = INT16_SIZE;
                break;

            case EXROutputType.HalfFloat:
                decoder.getter = ParseUint16;
                decoder.inputSize = INT16_SIZE;
                break;
        }
    } else if (decoder.type === 2) {
        // float
        switch (outputType) {

View on GitHub (pinned to 0592b347b8)

Solutions

  1. Re-export the texture so it contains R/G/B (or at least Y or R) channels
  2. Rename the primary channel to R or Y in the exporter settings
  3. Use a converter (oiiotool) to add RGB channels: `oiiotool depth.exr -ch R=Z,G=Z,B=Z -o rgb.exr`
  4. Verify with exrheader -info which channels the file actually holds

Example fix

// before: EXR with only a 'Z' depth channel
// after: convert so the channel is named R
// oiiotool depth.exr -ch R=Z -o single.exr
Defensive patterns

Strategy: validation

Validate before calling

// parse channel names from the EXR header before loading, or check with the export pipeline
// quick client-side guard: ensure the asset was exported as RGB/RGBA/Y, not a depth/AOV pass
if (isDepthOrAovPass(assetMeta)) throw new Error("use an RGB/RGBA EXR for textures");

Type guard

function isDecodableExrChannel(name: string): boolean {
  return ["R", "G", "B", "A", "Y"].includes(name);
}

Try / catch

try {
  await loader.loadAsync(file);
} catch (e) {
  if (/unsupported data channels/.test(String(e))) {
    console.warn("EXR has no R/G/B/A/Y channels (depth/AOV pass?) — converting");
    return loadConvertedTexture(url);
  }
  throw e;
}

Prevention

When it happens

Trigger: Raised in CreateDecoderAsync when header.channels contains no R/G/B/A/Y channel — e.g. a single-channel depth pass stored as 'Z' or 'depth.Y' with no Y/R channel, or a data/AOV EXR with only custom named channels.

Common situations: Loading depth-only or AOV render passes intended for compositors, custom CryEngine/prop channels, or mistyped channel names from a custom exporter.

Related errors


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