BabylonJS/Babylon.js · error

Invalid engine. Unable to create a canvas.

Error message

Invalid engine. Unable to create a canvas.

What it means

Image._rotate90 rotates the internal DOM image 90 degrees by drawing it onto an engine-created canvas (engine.createCanvas). It prefers the host scene's engine and falls back to EngineStore.LastCreatedEngine; with no engine available it throws because no 2D canvas surface can be created.

Source

Thrown at packages/dev/gui/src/2D/controls/image.pure.ts:340

            return;
        }

        this._stretch = value;

        this._markAsDirty();
    }

    /**
     * @internal
     */
    public _rotate90(n: number, preserveProperties: boolean = false): Image {
        const width = this._domImage.width;
        const height = this._domImage.height;

        // Should abstract platform instead of using LastCreatedEngine
        const engine = this._host?.getScene()?.getEngine() || EngineStore.LastCreatedEngine;
        if (!engine) {
            throw new Error("Invalid engine. Unable to create a canvas.");
        }
        const canvas = engine.createCanvas(height, width);

        const context = canvas.getContext("2d");

        context.translate(canvas.width / 2, canvas.height / 2);
        context.rotate((n * Math.PI) / 2);

        context.drawImage(this._domImage, 0, 0, width, height, -width / 2, -height / 2, width, height);

        const dataUrl: string = canvas.toDataURL("image/jpg");
        const rotatedImage = new Image(this.name + "rotated", dataUrl);

        if (preserveProperties) {
            rotatedImage._stretch = this._stretch;
            rotatedImage._autoScale = this._autoScale;
            rotatedImage._cellId = this._cellId;
            rotatedImage._cellWidth = n % 1 ? this._cellHeight : this._cellWidth;

View on GitHub (pinned to 0592b347b8)

Solutions

  1. Create the engine/scene and attach the image to a GUI host before calling rotate90().
  2. Ensure EngineStore.LastCreatedEngine exists (engine still alive) when the rotation runs.
  3. If rotation is triggered from an image onload callback, guard against engine disposal or re-check engine availability.
  4. In headless scenarios, provide a mock engine with createCanvas/getContext support.

Example fix

// before
const img = new Image("img", "url.png");
img.rotate90(); // no engine yet -> throws

// after
const engine = new Engine(canvas, true);
const scene = new Scene(engine);
const adt = AdvancedDynamicTexture.CreateFullscreenUI("ui", true, scene);
const img = new Image("img", "url.png");
adt.addControl(img);
img.rotate90();
Defensive patterns

Strategy: type-guard

Validate before calling

const engine = image.host?.getScene()?.getEngine() ?? EngineStore.LastCreatedEngine;
if (!engine) {
    throw new Error("Engine required to rotate image");
}
image.rotate90();

Type guard

function canCreateCanvas(e: unknown): e is { createCanvas(w: number, h: number): HTMLCanvasElement } {
    return !!e && typeof (e as any).createCanvas === "function";
}

Try / catch

try {
    image.rotate90();
} catch (e) {
    if (e instanceof Error && e.message.includes("Invalid engine")) {
        console.error("No engine available to create canvas for rotation:", e);
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: Calling image.rotate90() (or APIs that trigger _rotate90) when the image's host has no scene/engine (e.g. sourceHost/linked GUI not yet attached) and EngineStore.LastCreatedEngine is null — engine-less, headless, or post-dispose contexts.

Common situations: Manipulating Image controls before the engine/scene exists; using the pure GUI build standalone; engine disposed while a delayed image-load callback rotates the image; unit tests without a Babylon engine.

Related errors


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