pixijs/pixijs · error · Error

[HTMLSource] resource must be a direct child of the owning c

Error message

[HTMLSource] resource must be a direct child of the owning canvas. Append the element to the canvas before constructing this source.

What it means

The third HTMLSource gate: even after a canvas is found, the resource must be a DIRECT child of that canvas (resource.parentElement === canvas). HTML-in-Canvas integration requires this parent-child relationship so the browser associates the element with the correct canvas surface. An element nested deeper, or attached to a different parent, fails this check.

Source

Thrown at src/html-source/HTMLSource.ts:269

        {
            throw new Error('[HTMLSource] resource is required.');
        }

        super(options);

        const canvas = options.canvas ?? this._inferCanvas(options.resource);

        if (!canvas)
        {
            throw new Error(
                // eslint-disable-next-line max-len
                '[HTMLSource] Could not determine the owning canvas. Append the element to the canvas before constructing this source, or pass the `canvas` option.',
            );
        }

        if (options.resource.parentElement !== canvas)
        {
            throw new Error(
                // eslint-disable-next-line max-len
                '[HTMLSource] resource must be a direct child of the owning canvas. Append the element to the canvas before constructing this source.',
            );
        }

        this.canvas = canvas;
        this._autoUpdate = options.autoUpdate !== false;
        this._onPaintBound = this._onPaint.bind(this);

        // Without requestPaint (or with auto-update off) there is no first paint to wait for.
        this._isReady = !this._autoUpdate || !canvas.requestPaint;

        if (options.autoLayout !== false)
        {
            canvas.setAttribute('layoutsubtree', '');
        }

        if (this._autoUpdate)

View on GitHub (pinned to 4b141e3ced)

Solutions

  1. Append the resource directly to the canvas element, not to an intermediate wrapper.
  2. Remove intermediate containers or flatten the DOM structure under the canvas.
  3. If a wrapper is required for layout, make the wrapper itself the HTMLSource resource and parent it to the canvas.
  4. After any DOM move, re-verify resource.parentElement === canvas.

Example fix

// before
canvas.appendChild(wrapper);
wrapper.appendChild(el);
const source = new HTMLSource({ resource: el, canvas });

// after
canvas.appendChild(el);
const source = new HTMLSource({ resource: el, canvas });
Defensive patterns

Strategy: validation

Validate before calling

if (resource.parentElement !== canvas) {
  canvas.appendChild(resource);
}
const source = new HTMLSource({ resource, canvas });

Type guard

function isDirectChildOf(el: HTMLElement, canvas: HTMLCanvasElement): boolean {
  return el.parentElement === canvas;
}

Prevention

When it happens

Trigger: Appending the resource to a wrapper div that is itself a child of the canvas (element is a grandchild); moving the element to another container after construction; passing a canvas via options.canvas that is not the element's actual parent.

Common situations: Wrapping overlays in a positioning container for layout; framework that inserts intermediate wrapper nodes; re-parenting during animations.

Related errors


AI-assisted analysis of pixijs/pixijs@4b141e3ced (2026-08-12). Data as JSON: /api/errors/2c94f9d5e9daee4a. Report an issue: GitHub.