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

  1. Ensure a Babylon engine is created (new Engine(canvas, ...) / EngineFactory.CreateAsync) before adding a ColorPicker to the GUI.
  2. Check EngineStore.LastCreatedEngine is not null before constructing controls that draw canvas imagery.
  3. If the engine was disposed, recreate it or remove the GUI before disposal.
  4. 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

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


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