phaserjs/phaser · error · Error

Buffer too small for layout

Error message

Buffer too small for layout

What it means

Thrown by WebGLVertexBufferLayoutWrapper when a buffer argument is supplied whose byteLength is smaller than the required bufferSize = layout.stride * layout.count. The wrapper refuses to under-allocate because binding a too-small buffer to the described attributes would read out of bounds at draw time.

Source

Thrown at src/renderer/webgl/wrappers/WebGLVertexBufferLayoutWrapper.js:61

        /**
         * The completed attribute buffer layout, describing the stride,
         * attributes, their types, sizes, byte counts, and byte offsets
         * within the vertex buffer.
         *
         * @name Phaser.Renderer.WebGL.Wrappers.WebGLVertexBufferLayoutWrapper#layout
         * @type {Phaser.Types.Renderer.WebGL.WebGLAttributeBufferLayout}
         * @since 4.0.0
         */
        this.layout = layout;

        // Fill in the layout with the stride
        // and per-attribute bytes and offset.
        this.completeLayout(layout);

        var bufferSize = layout.stride * layout.count;
        if (buffer && buffer.byteLength < bufferSize)
        {
            throw new Error('Buffer too small for layout');
        }

        /**
         * The WebGLBufferWrapper holding the vertex data for this layout.
         *
         * @name Phaser.Renderer.WebGL.Wrappers.WebGLVertexBufferLayoutWrapper#buffer
         * @type {Phaser.Renderer.WebGL.Wrappers.WebGLBufferWrapper}
         * @since 4.0.0
         */
        this.buffer = buffer || renderer.createVertexBuffer(new ArrayBuffer(bufferSize), layout.usage);
    },

    /**
     * Complete the layout of the provided attribute buffer layout.
     * This will fill in the stride, byte counts, and offsets.
     * In addition, it will convert any GLenums specified as strings
     * to their numeric values.
     * This mutates the layout.

View on GitHub (pinned to 41be1e462b)

Solutions

  1. Size the buffer to at least layout.stride * layout.count bytes.
  2. If you want the wrapper to allocate for you, omit the buffer argument so it creates one of the correct size.
  3. Recompute layout.count when the capacity changes and reallocate the buffer to match.
  4. Audit stride math (sum of attribute sizes * components) to ensure stride is not inflated, forcing an oversized buffer.

Example fix

// before
const buf = renderer.createVertexBuffer(new ArrayBuffer(1024)); // too small
new WebGLVertexBufferLayoutWrapper(renderer, { stride: 16, count: 100, attributes: [...] }, buf);

// after
const buf = renderer.createVertexBuffer(new ArrayBuffer(16 * 100));
new WebGLVertexBufferLayoutWrapper(renderer, { stride: 16, count: 100, attributes: [...] }, buf);
// or omit buffer to auto-allocate
Defensive patterns

Strategy: validation

Validate before calling

function assertBufferBigEnough(buffer, stride, count) {
  const need = stride * count;
  if (buffer && buffer.byteLength < need) {
    throw new RangeError(`Buffer ${buffer.byteLength} < required ${need}`);
  }
}

Type guard

function bufferFitsLayout(buffer, layout) { return !buffer || buffer.byteLength >= layout.stride * layout.count; }

Prevention

When it happens

Trigger: Constructing WebGLVertexBufferLayoutWrapper with an explicit buffer that was allocated for fewer vertices than layout.count, or a layout whose count/stride grew after the buffer was created; passing a shared/recycled buffer that is too small for the new layout.

Common situations: Pre-allocating a vertex buffer for N sprites then increasing layout.count; reuse of a buffer across layouts with different stride; off-by-one in count when sizing the ArrayBuffer; changing the attribute set (and thus stride) without re-sizing the buffer.

Related errors


AI-assisted analysis of phaserjs/phaser@41be1e462b (2026-08-13). Data as JSON: /api/errors/f8c592fbe1a0c0d9. Report an issue: GitHub.