BabylonJS/Babylon.js · error

Unable to create Occlusion Query

Error message

Unable to create Occlusion Query

What it means

ThinEngine.createQuery wraps gl.createQuery() to allocate a WebGL occlusion query object. WebGL guarantees non-null in spec-compliant implementations, but if the underlying GL call returns null (context lost or driver failure) Babylon throws this error instead of returning an invalid query handle. Any use of scene.setRenderingAutoClearDepthStencil with occlusion or the OcclusionQuery API can hit it.

Source

Thrown at packages/dev/core/src/Engines/Extensions/engine.query.pure.ts:23

import { type OcclusionQuery } from "../AbstractEngine/abstractEngine.query.pure";
import { ThinEngine } from "../../Engines/thinEngine.pure";
import { _TimeToken } from "../../Instrumentation/timeToken";

let _Registered = false;
/**
 * Register side effects for enginesExtensionsEngineQuery.
 * Safe to call multiple times; only the first call has an effect.
 */
export function RegisterEnginesExtensionsEngineQuery(): void {
    if (_Registered) {
        return;
    }
    _Registered = true;

    ThinEngine.prototype.createQuery = function (): OcclusionQuery {
        const query = this._gl.createQuery();
        if (!query) {
            throw new Error("Unable to create Occlusion Query");
        }
        return query;
    };

    ThinEngine.prototype.deleteQuery = function (query: OcclusionQuery): ThinEngine {
        this._gl.deleteQuery(query);

        return this;
    };

    ThinEngine.prototype.isQueryResultAvailable = function (query: OcclusionQuery): boolean {
        return this._gl.getQueryParameter(query, this._gl.QUERY_RESULT_AVAILABLE) as boolean;
    };

    ThinEngine.prototype.getQueryResult = function (query: OcclusionQuery): number {
        return this._gl.getQueryParameter(query, this._gl.QUERY_RESULT) as number;
    };

View on GitHub (pinned to 0592b347b8)

Solutions

  1. Listen for 'webglcontextlost' and re-create the engine/restore context
  2. Wrap query creation in try-catch and disable occlusion queries on failure
  3. Reduce number of meshes using occlusion queries
  4. Update GPU/browser to fix driver-level query creation bugs
  5. Re-run the operation after context restore (webglcontextrestored)

Example fix

// before
const query = engine.createQuery();
// after
let query = null;
try {
  query = engine.createQuery();
} catch (e) {
  mesh.occlusionQueryEnabled = false; // degrade gracefully
}
Defensive patterns

Strategy: try-catch

Validate before calling

function canCreateQuery(engine) {
  return !engine.isDisposed && !!(engine as any)._gl && typeof (engine as any)._gl.createQuery === 'function';
}

Type guard

function hasLiveContext(engine): boolean {
  return !engine.isDisposed && !!(engine as any)._gl;
}

Try / catch

let query: BABYLON.OcclusionQuery | null = null;
try {
  query = engine.createQuery();
} catch (e) {
  if (String(e?.message).includes('Occlusion Query')) {
    mesh.occlusionQueryEnabled = false; // disable occlusion queries
  } else { throw e; }
}

Prevention

When it happens

Trigger: Calling ThinEngine.createQuery() (directly or via mesh occlusion queries: mesh.alwaysSelectAsActiveMesh=false with occlusion enabled) when the WebGL context is lost or gl.createQuery() fails.

Common situations: Tab/background context loss while using occlusion queries; old drivers with faulty query object allocation; running occlusion queries after GPU reset; heavy use of many query objects.

Related errors


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