BabylonJS/Babylon.js · error

Invalid engine. Unable to create a canvas.

Error message

Invalid engine. Unable to create a canvas.

What it means

Control._MeasureFontHeight (font-height caching helper) requires an engine to call engine.getFontOffset(font). It uses the passed engineToUse or falls back to EngineStore.LastCreatedEngine; when neither exists it throws, reusing the generic 'unable to create a canvas' message because font metrics depend on engine canvas facilities.

Source

Thrown at packages/dev/gui/src/2D/controls/control.pure.ts:2830

    /** VERTICAL_ALIGNMENT_CENTER */
    public static get VERTICAL_ALIGNMENT_CENTER(): number {
        return Control._VERTICAL_ALIGNMENT_CENTER;
    }

    private static _FontHeightSizes: { [key: string]: { ascent: number; height: number; descent: number } } = {};

    /**
     * @internal
     */
    public static _GetFontOffset(font: string, engineToUse?: AbstractEngine): { ascent: number; height: number; descent: number } {
        if (Control._FontHeightSizes[font]) {
            return Control._FontHeightSizes[font];
        }

        const engine = engineToUse || EngineStore.LastCreatedEngine;
        if (!engine) {
            throw new Error("Invalid engine. Unable to create a canvas.");
        }

        const result = engine.getFontOffset(font);
        Control._FontHeightSizes[font] = result;

        return result;
    }

    /**
     * Creates a Control from parsed data
     * @param serializedObject defines parsed data
     * @param host defines the hosting AdvancedDynamicTexture
     * @param urlRewriter defines an url rewriter to update urls before sending them to the controls
     * @returns a new Control
     */
    public static Parse(serializedObject: any, host: AdvancedDynamicTexture, urlRewriter?: (url: string) => string): Control {
        const controlType = Tools.Instantiate("BABYLON.GUI." + serializedObject.className);
        const control = SerializationHelper.Parse(

View on GitHub (pinned to 0592b347b8)

Solutions

  1. Create a Babylon engine (and scene) before instantiating/measuring text-bearing controls.
  2. Pass an explicit engine via the API that accepts engineToUse instead of relying on LastCreatedEngine fallback.
  3. Ensure the engine is not disposed before GUI layout completes; dispose GUI first.
  4. In tests, seed EngineStore via a mock engine or avoid font measurement paths.

Example fix

// before
const tb = new TextBlock("t", "hello"); // measures font, throws if no engine

// after
const engine = new Engine(canvas, true);
const scene = new Scene(engine);
const adt = AdvancedDynamicTexture.CreateFullscreenUI("ui", true, scene);
const tb = new TextBlock("t", "hello");
adt.addControl(tb);
Defensive patterns

Strategy: validation

Validate before calling

import { EngineStore } from "@babylonjs/core/Engines/engineStore";
if (!EngineStore.LastCreatedEngine) {
    throw new Error("Engine required before text controls can measure fonts");
}
const tb = new TextBlock("t", "hello");

Type guard

function engineAvailable(e: unknown): e is { getFontOffset(font: string): { offset: number; height: number } } {
    return !!e && typeof (e as any).getFontOffset === "function";
}

Try / catch

try {
    textBlock.text = "hello";
} catch (e) {
    if (e instanceof Error && e.message.includes("Invalid engine")) {
        console.error("Cannot measure font without an engine:", e);
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: Any Control text measurement (e.g. setting text, computing font height for TextBlock/Button) when no engine has been created, the engine was disposed, or the host/scene was built in a context without LastCreatedEngine — e.g. pure-mode usage without supplying engineToUse.

Common situations: Preloading or laying out GUI controls before engine init; SSR/Node rendering of GUI trees; tests constructing TextBlock with fonts; disposing the engine while GUI is still measuring on resize events.

Related errors


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