pixijs/pixijs · error · Error

[RenderTarget] cannot attach a depth-stencil texture to the

Error message

[RenderTarget] cannot attach a depth-stencil texture to the screen — the canvas owns its own depth/stencil buffers. Render to a texture target instead.

What it means

Thrown by RenderTarget when a depth-stencil texture is attached to a root (screen) target. The screen/canvas owns its own depth and stencil buffers provided by the context (WebGL default framebuffer or the WebGPU canvas configuration), so an external depth-stencil texture cannot be bound there.

Source

Thrown at src/rendering/renderers/shared/renderTarget/RenderTarget.ts:277

                colorAttachments.push({
                    texture: texture.source,
                    loadOp: 'clear',
                    storeOp: 'store',
                });
            });
        }

        const wantsDepthStencilTexture = opts.depthStencilTexture === true;

        this._depth = !!(opts.depth || wantsDepthStencilTexture);
        this._stencil = !!(opts.stencil || wantsDepthStencilTexture);

        if (opts.depthStencilTexture instanceof Texture
            || opts.depthStencilTexture instanceof TextureSource)
        {
            if (opts.isRoot)
            {
                throw new Error('[RenderTarget] cannot attach a depth-stencil texture to the screen — '
                    + 'the canvas owns its own depth/stencil buffers. Render to a texture target instead.');
            }

            depthStencilAttachment = {
                texture: opts.depthStencilTexture.source,
            };
        }
        else if ((wantsDepthStencilTexture && !opts.isRoot)
            || ((opts.stencil || opts.depth) && colorAttachments.length === 0))
        {
            // an explicit texture request (depthStencilTexture: true) or a depth-only target.
            // Plain depth/stencil flags create no texture — each backend picks the cheapest
            // resource (renderbuffer on WebGL, internal texture on WebGPU, context buffers
            // for the screen)
            depthStencilAttachment = this._createDepthStencilTexture(opts.width, opts.height, opts.resolution);
        }

        return {

View on GitHub (pinned to 4b141e3ced)

Solutions

  1. Drop `depthStencilTexture` from the root target — let the canvas manage its own depth/stencil via `depth`/`stencil` flags or renderer configuration.
  2. Render into an offscreen texture target (isRoot: false) if you must share a specific depth-stencil texture.
  3. Separate your 'screen pass' configuration object from your 'offscreen pass' configuration so root-specific options never leak.

Example fix

// before
new RenderTarget({ isRoot: true, depthStencilTexture: sharedDepthTex });
// after
new RenderTarget({ isRoot: true, depth: true, stencil: true });
Defensive patterns

Strategy: validation

Validate before calling

function assertRootOpts(opts) {
  if (opts.isRoot && (opts.depthStencilTexture instanceof Texture || opts.depthStencilTexture instanceof TextureSource)) {
    throw new Error('Root cannot take depthStencilTexture');
  }
}

Type guard

function isRootSafeOpts(opts): boolean {
  return !opts.isRoot || !(opts.depthStencilTexture instanceof Texture || opts.depthStencilTexture instanceof TextureSource);
}

Prevention

When it happens

Trigger: Constructing a RenderTarget with `isRoot: true` together with `depthStencilTexture: <Texture|TextureSource>` (or passing such a Texture through the root render-surface options).

Common situations: Reusing a depth-stencil texture across both screen and offscreen passes; copying an offscreen RenderTarget config verbatim into the root target; misconfiguring the application's main render surface.

Related errors


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