stride3d/stride · error · ArgumentException

Binding describes an array larger than dataOuter

Error message

Binding describes an array larger than dataOuter ({dataOuter.Length} < {binding.Offset} + {binding.Count} * {binding.Stride})

What it means

The VertexBufferHelper constructor throws ArgumentException when the backing byte array (dataOuter) is smaller than the vertex buffer binding requires: binding.Offset + binding.Count * binding.Stride. The helper will read the entire vertex buffer from the array, so the array must contain at least that many bytes. The library throws immediately in the constructor to prevent out-of-bounds reads later.

Solutions

  1. Re-fetch the full vertex buffer data so dataOuter contains at least binding.Offset + binding.Count * binding.Stride bytes
  2. Verify VertexBufferBinding values: Offset, Count (number of vertices) and Stride match the actual data array size
  3. If you only have partial data, reduce binding.Count to (dataOuter.Length - binding.Offset) / binding.Stride
  4. Log dataOuter.Length and the computed required size to see which side of the mismatch is wrong

Example fix

// before
var helper = new VertexBufferHelper(binding, partialData, out count);
// after
int required = binding.Offset + binding.Count * binding.Stride;
if (partialData.Length < required)
    throw new InvalidOperationException($"Need {required} bytes, have {partialData.Length}");
var helper = new VertexBufferHelper(binding, partialData, out count);
Defensive patterns

Strategy: validation

Validate before calling

int required = binding.Offset + binding.Count * binding.Stride;
if (data.Length < required)
    throw new InvalidOperationException($"Vertex data too small: {data.Length} < {required}");

Type guard

static bool BufferFitsBinding(VertexBufferBinding b, byte[] data) => data.Length >= b.Offset + b.Count * b.Stride;

Try / catch

try { var helper = new VertexBufferHelper(binding, data, out var count); ... }
catch (ArgumentException ex) { logger.Error(ex, "Vertex buffer smaller than binding describes"); throw; }

Prevention

When it happens

Trigger: Constructing VertexBufferHelper with a byte[] retrieved from the GPU that was truncated, or with a binding whose Count/Offset/Stride describe more data than the array holds (e.g. binding.Count set to the element count while the array only holds part of the buffer).

Common situations: Manually rebuilding a vertex buffer after editing mesh data without resizing the byte array; mixing up element count vs byte count when filling VertexBufferBinding; a serializer that truncated the buffer data.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14). Data as JSON: /api/errors/58fe208744997378. Report an issue: GitHub.

Appendix: source

Thrown at sources/engine/Stride.Graphics/VertexBufferHelper.cs:54

    public Span<byte> DataInner => DataOuter.AsSpan(Binding.Offset, Binding.Count * Binding.Stride);

    /// <inheritdoc cref="MeshExtension.AsReadable(VertexBufferBinding, IServiceRegistry, out VertexBufferHelper, out int)"/>
    public VertexBufferHelper(VertexBufferBinding binding, IServiceRegistry services, out int count) 
        : this(binding, MeshExtension.FetchBufferContentOrThrow(binding.Buffer, services), out count)
    {
    }

    /// <summary>
    /// Create the helper from existing data instead of trying to fetch the buffer automatically
    /// </summary>
    /// <exception cref="ArgumentException">
    /// <paramref name="dataOuter"/> does not match the binding definition provided,
    /// <paramref name="dataOuter"/> must be the entire vertex buffer
    /// </exception>
    public VertexBufferHelper(VertexBufferBinding binding, byte[] dataOuter, out int count)
    {
        if (dataOuter.Length < binding.Offset + binding.Count * binding.Stride)
            throw new ArgumentException($"Binding describes an array larger than {nameof(dataOuter)} ({dataOuter.Length} < {binding.Offset} + {binding.Count} * {binding.Stride})");

        DataOuter = dataOuter;
        Binding = binding;
        count = Binding.Count;
    }

    /// <summary>
    /// Extract individual element from each vertex contained in this vertex buffer and copies them into <paramref name="buffer"/>
    /// </summary>
    /// <param name="buffer">
    /// The buffer which will be written to, must have exactly the same amount of items as there are <b>vertices</b> in the buffer
    /// </param>
    /// <param name="semanticIndex">
    /// The semantic to read with that index, starts at zero.<br/>
    /// For example, to sample the second TextureCoordinate, you would use
    /// <code>
    /// <![CDATA[
    /// helper.Copy<TextureCoordinateSemantic, Vector2>(myUvs, 1);

View on GitHub (pinned to 96fad776d2)