BabylonJS/Babylon.js · error
Invalid engine. Unable to create a canvas.
Error message
Invalid engine. Unable to create a canvas.
What it means
ColorPicker._createColorWheelCanvas needs an engine-owned 2D canvas (engine.createCanvas) to draw the color wheel image. It falls back to EngineStore.LastCreatedEngine, and when no engine exists at all it throws because no canvas can be created.
Source
Thrown at packages/dev/gui/src/2D/controls/colorpicker.pure.ts:223
private _drawCircle(centerX: number, centerY: number, radius: number, context: ICanvasRenderingContext) {
context.beginPath();
context.arc(centerX, centerY, radius + 1, 0, 2 * Math.PI, false);
context.lineWidth = 3;
context.strokeStyle = "#333333";
context.stroke();
context.beginPath();
context.arc(centerX, centerY, radius, 0, 2 * Math.PI, false);
context.lineWidth = 3;
context.strokeStyle = "#ffffff";
context.stroke();
}
private _createColorWheelCanvas(radius: number, thickness: number): ICanvas {
// Shoudl abstract platform instead of using LastCreatedEngine
const engine = EngineStore.LastCreatedEngine;
if (!engine) {
throw new Error("Invalid engine. Unable to create a canvas.");
}
const canvas = engine.createCanvas(radius * 2, radius * 2);
const context = canvas.getContext("2d");
const image = context.getImageData(0, 0, radius * 2, radius * 2);
const data = image.data;
const color = this._tmpColor;
const maxDistSq = radius * radius;
const innerRadius = radius - thickness;
const minDistSq = innerRadius * innerRadius;
for (let x = -radius; x < radius; x++) {
for (let y = -radius; y < radius; y++) {
const distSq = x * x + y * y;
if (distSq > maxDistSq || distSq < minDistSq) {
continue;
}
View on GitHub (pinned to 0592b347b8)
Solutions
- Ensure a Babylon engine is created (new Engine(canvas, ...) / EngineFactory.CreateAsync) before adding a ColorPicker to the GUI.
- Check EngineStore.LastCreatedEngine is not null before constructing controls that draw canvas imagery.
- If the engine was disposed, recreate it or remove the GUI before disposal.
- For headless tests, stub/provide a mock engine exposing createCanvas and 2D context APIs.
Example fix
// before
const adt = AdvancedDynamicTexture.CreateFullscreenUI("ui"); // no engine created yet
const picker = new ColorPicker();
// after
const engine = new Engine(canvas, true);
const scene = new Scene(engine);
const adt = AdvancedDynamicTexture.CreateFullscreenUI("ui", true, scene);
const picker = new ColorPicker(); Defensive patterns
Strategy: type-guard
Validate before calling
import { EngineStore } from "@babylonjs/core/Engines/engineStore";
if (!EngineStore.LastCreatedEngine) {
throw new Error("Create a Babylon engine before using ColorPicker");
}
const picker = new ColorPicker(); Type guard
function hasEngine(e: unknown): e is { createCanvas(w: number, h: number): { getContext(c: "2d"): CanvasRenderingContext2D } } {
return !!e && typeof (e as any).createCanvas === "function";
} Try / catch
try {
gui.addControl(new ColorPicker());
} catch (e) {
if (e instanceof Error && e.message.includes("Invalid engine")) {
console.error("No Babylon engine available for canvas drawing:", e);
} else {
throw e;
}
} Prevention
- Always create the engine (and scene) before constructing any GUI controls.
- Check EngineStore.LastCreatedEngine in app bootstrap before GUI init.
- Never dispose the engine while the GUI is still attached; dispose GUI/ADT first.
- In tests/headless environments, install a mock engine that provides createCanvas.
When it happens
Trigger: Creating/showing a ColorPicker control in a headless or engine-less context — e.g. building GUI controls before EngineFactory/Engine is created, after engine.dispose(), or in a pure/DOM-only environment where LastCreatedEngine is null.
Common situations: Unit-testing GUI controls without a Babylon engine; instantiating the GUI before scene/engine initialization; using the pure (non-scene) build in Node; disposal-order bugs where the engine is gone but the GUI is still drawn.
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/9e9aa27b6a89bc0b.
Report an issue: GitHub.