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
- Create a Babylon engine (and scene) before instantiating/measuring text-bearing controls.
- Pass an explicit engine via the API that accepts engineToUse instead of relying on LastCreatedEngine fallback.
- Ensure the engine is not disposed before GUI layout completes; dispose GUI first.
- 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
- Initialize engine + scene before building any text-bearing controls (TextBlock, Button, InputTextBox).
- Guard resize/layout handlers so they skip font measurement after engine.dispose().
- Use APIs accepting an explicit engineToUse rather than the LastCreatedEngine fallback when possible.
- In SSR/pure contexts, defer GUI construction until a real or mock engine exists.
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
- Invalid engine. Unable to create a canvas.
- Invalid engine. Unable to create a canvas.
- Failed to get client rect for rendering canvas
- Recast is not initialized. Please call InitRecast first.
- There is no NavMesh generated.
AI-assisted analysis of BabylonJS/Babylon.js@0592b347b8 (2026-08-30).
Data as JSON: /api/errors/a12dc64ba956431f.
Report an issue: GitHub.