BabylonJS/Babylon.js · error

${context}: Uri is missing or the binary glTF is missing its

Error message

${context}: Uri is missing or the binary glTF is missing its binary chunk

What it means

With MSFT_lod + range requests (HTTP range loading), buffer data must come either from a uri or from the .glb binary chunk. When useRangeRequests is enabled, the buffer has no uri, and the loader has no bin chunk stored (e.g. the .glb lacked its BIN chunk or a .gltf was loaded with range requests), there is no data source and loadBufferAsync throws.

Source

Thrown at packages/dev/loaders/src/glTF/2.0/Extensions/MSFT_lod.pure.ts:310

            this._loader.log(`deferred`);
            const previousIndexLOD = this._materialIndexLOD - 1;
            this._materialSignalLODs[previousIndexLOD] = this._materialSignalLODs[previousIndexLOD] || new Deferred<void>();
            return this._materialSignalLODs[previousIndexLOD].promise.then(async () => {
                return await this._loader.loadUriAsync(context, property, uri);
            });
        }

        return null;
    }

    /**
     * @internal
     */
    // eslint-disable-next-line no-restricted-syntax
    public loadBufferAsync(context: string, buffer: IBuffer, byteOffset: number, byteLength: number): Nullable<Promise<ArrayBufferView>> {
        if (this._loader.parent.useRangeRequests && !buffer.uri) {
            if (!this._loader.bin) {
                throw new Error(`${context}: Uri is missing or the binary glTF is missing its binary chunk`);
            }

            const loadAsync = async (bufferLODs: Array<IBufferInfo>, indexLOD: number) => {
                const start = byteOffset;
                const end = start + byteLength - 1;
                let bufferLOD = bufferLODs[indexLOD];
                if (bufferLOD) {
                    bufferLOD.start = Math.min(bufferLOD.start, start);
                    bufferLOD.end = Math.max(bufferLOD.end, end);
                } else {
                    bufferLOD = { start: start, end: end, loaded: new Deferred() };
                    bufferLODs[indexLOD] = bufferLOD;
                }

                return await bufferLOD.loaded.promise.then((data) => {
                    return new Uint8Array(data.buffer, data.byteOffset + byteOffset - bufferLOD.start, byteLength);
                });
            };

View on GitHub (pinned to 0592b347b8)

Solutions

  1. Use a .glb file that contains a valid binary (BIN) chunk when useRangeRequests is true.
  2. Add a uri to the buffer in the glTF so it can be fetched directly.
  3. Disable useRangeRequests (loader.parent.useRangeRequests = false) if full files are available.

Example fix

// before
loader.useRangeRequests = true; // loading .gltf without buffer uri
// after
loader.useRangeRequests = true; // with .glb containing BIN chunk
// or: loader.useRangeRequests = false;
Defensive patterns

Strategy: fallback

Validate before calling

if (loader.useRangeRequests && !isGlb(bufferSource)) {
  throw new Error('Range requests require a .glb with a binary chunk');
}

Try / catch

try { await loader.loadAsync(url); } catch (e) {
  if (e.message.includes('binary chunk')) {
    loader.useRangeRequests = false;
    return loader.loadAsync(url); // fallback without range requests
  } throw e;
}

Prevention

When it happens

Trigger: Loading with MSFT_lod extension and loader.parent.useRangeRequests = true where buffer.uri is absent AND loader.bin is null (glb without binary chunk, or range requests on a plain .gltf).

Common situations: Enabling useRangeRequests for LOD streaming on .gltf files (JSON-only) instead of .glb; stripping the BIN chunk from a .glb during optimization; serving .glb files without proper range support and combining configs incorrectly.

Related errors


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