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
- Re-export the texture so it contains R/G/B (or at least Y or R) channels
- Rename the primary channel to R or Y in the exporter settings
- Use a converter (oiiotool) to add RGB channels: `oiiotool depth.exr -ch R=Z,G=Z,B=Z -o rgb.exr`
- 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
- Export textures as RGB/RGBA, not depth or AOV passes
- Rename custom primary channels to R or Y at export
- Document which passes are texture-loadable in your asset pipeline
- Inspect channel names with exrheader -info before shipping
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
- Unsupported pixelType ${decoder.type} for ${header.compressi
- Unsupported file format
- Error in HufUnpackEncTable
- Invalid table entry
- hufDecode issues
AI-assisted analysis of BabylonJS/Babylon.js@0592b347b8 (2026-08-30).
Data as JSON: /api/errors/902a150456e7836a.
Report an issue: GitHub.