pixijs/pixijs · error · Error

[RenderTargetSystem] layer must be 0 when rendering to 2D te

Error message

[RenderTargetSystem] layer must be 0 when rendering to 2D textures in WebGL.

What it means

Inside the per-attachment bind loop, when a color attachment's GL source target is TEXTURE_2D, the layer parameter must be 0 (2D textures have no slices). If a non-zero layer is requested against a 2D texture, framebufferTexture2D cannot honor it, so the adaptor throws. This catches mismatched render-target configs where a layer is set but the texture is not a 2D array / cube map.

Source

Thrown at src/rendering/renderers/gl/renderTarget/GlRenderTargetAdaptor.ts:188

        this.bindFramebuffer(gpuRenderTarget.framebuffer);

        if (
            !renderTarget.isRoot
            && renderTarget.colorAttachments.length > 0
            && (gpuRenderTarget._attachedMipLevel !== mipLevel
                || gpuRenderTarget._attachedLayer !== layer)
        )
        {
            renderTarget.colorAttachments.forEach((attachment, i) =>
            {
                const colorTexture = attachment.texture;
                const glSource = this._renderer.texture.getGlSource(colorTexture);

                if (glSource.target === gl.TEXTURE_2D)
                {
                    if (layer !== 0)
                    {
                        throw new Error('[RenderTargetSystem] layer must be 0 when rendering to 2D textures in WebGL.');
                    }

                    gl.framebufferTexture2D(
                        gl.FRAMEBUFFER,
                        gl.COLOR_ATTACHMENT0 + i,
                        gl.TEXTURE_2D,
                        glSource.texture,
                        mipLevel
                    );
                }
                else if (glSource.target === (gl as any).TEXTURE_2D_ARRAY)
                {
                    if (this._renderer.context.webGLVersion < 2)
                    {
                        throw new Error('[RenderTargetSystem] Rendering to 2D array textures requires WebGL2.');
                    }

                    gl.framebufferTextureLayer(

View on GitHub (pinned to 4b141e3ced)

Solutions

  1. Pass layer=0 (or omit it) when the render target's color attachment is a 2D texture.
  2. If layered rendering is intended, back the render target with a 2D array or cube texture, not a 2D texture.
  3. Inspect each attachment's GL source target before deciding whether to pass a non-zero layer.
  4. Centralize layer/texture-type validation in your render-pass builder.

Example fix

// before
const rt = new RenderTarget({ colorTextures: [tex2d] });
renderTargetSystem.bind(rt, undefined, 0, 1); // layer 1 on 2D

// after
const rt = new RenderTarget({ colorTextures: [tex2d] });
renderTargetSystem.bind(rt, undefined, 0, 0);
Defensive patterns

Strategy: validation

Validate before calling

if (layer !== 0 && glSource.target === gl.TEXTURE_2D) {
  throw new Error('layer must be 0 for TEXTURE_2D attachments');
}

Type guard

function isTexture2DTarget(target: number, gl: WebGL2RenderingContext): boolean {
  return target === gl.TEXTURE_2D;
}

Prevention

When it happens

Trigger: Binding a RenderTarget whose color texture is a plain 2D texture but passing layer !== 0; reusing a render pass that specifies a layer with a 2D-texture-backed target.

Common situations: Generic layer-handling code that applies a non-zero layer uniformly without checking the texture type; migrating a cube-map render path to a 2D texture but leaving the layer argument in place.

Related errors


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