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.Is32Bit ? 4 : 2)}) What it means
IndexBufferHelper wraps existing index buffer data for reading; the constructor validates that dataOuter is large enough to hold the binding's full view: Offset + Count * (2 or 4 bytes for 16/32-bit indices). If the array is smaller, ArgumentException is thrown with the exact sizes involved. This prevents out-of-range reads when interpreting mesh index data.
Solutions
- Pass the full buffer data array from FetchBufferContentOrThrow/TryFetchBufferContent for the same buffer the binding was built from.
- Verify binding.Offset and binding.Count against the actual data length before constructing.
- Check Is32Bit matches the buffer's actual index format (IndexBufferElementSize).
Example fix
// before
var helper = new IndexBufferHelper(binding, truncatedData, out var count);
// after
int required = binding.Offset + binding.Count * (binding.Is32Bit ? 4 : 2);
if (data.Length < required) throw new InvalidOperationException($"need {required} bytes, got {data.Length}");
var helper = new IndexBufferHelper(binding, data, out var count); Defensive patterns
Strategy: validation
Validate before calling
int required = binding.Offset + binding.Count * (binding.Is32Bit ? 4 : 2);
if (dataOuter == null || dataOuter.Length < required)
throw new InvalidOperationException($"Index data too small: need {required}, have {dataOuter?.Length ?? 0}"); Type guard
bool FitsBinding(IndexBufferBinding b, byte[] d) => d != null && d.Length >= b.Offset + b.Count * (b.Is32Bit ? 4 : 2);
Try / catch
try { var helper = new IndexBufferHelper(binding, data, out var count); }
catch (ArgumentException ex) { log.Error("index buffer data truncated", ex); } Prevention
- Fetch data with TryFetchBufferContent for the same buffer as the binding
- Keep binding Offset/Count in sync with loaded data
- Match Is32Bit to the buffer's index element size
When it happens
Trigger: Constructing IndexBufferHelper (directly or via MeshExtension.AsReadable) with a byte[] shorter than binding.Offset + binding.Count * indexSize, e.g. reading from a truncated buffer, wrong vertex/index buffer mix-up, or a binding whose Count was computed for different data.
Common situations: Mesh assets whose buffer data was not fully loaded (stale AttachedReference length); offset/count mismatch after editing a mesh; reading a 32-bit index buffer with a 16-bit assumption or vice versa.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- Binding describes an array larger than dataOuter
- Cannot generate more than 65535 indices on feature level HW…
- Control points apply only to PrimitiveType.PatchList
- destination length does not match the amount of indices…
- destination length does not match the amount of vertices…
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/a02f0446fc7988f0.
Report an issue: GitHub.
Appendix: source
Thrown at sources/engine/Stride.Graphics/IndexBufferHelper.cs:43
public readonly byte[] DataOuter;
public readonly IndexBufferBinding Binding;
/// <summary>
/// Effective index buffer, handles the binding offset
/// </summary>
public Span<byte> DataInner => DataOuter.AsSpan(Binding.Offset, Binding.Count * (Binding.Is32Bit ? 4 : 2));
/// <inheritdoc cref="MeshExtension.AsReadable(IndexBufferBinding, IServiceRegistry, out IndexBufferHelper, out int)"/>
public IndexBufferHelper(IndexBufferBinding binding, IServiceRegistry services, out int count)
: this(binding, MeshExtension.FetchBufferContentOrThrow(binding.Buffer, services), out count)
{
}
/// <inheritdoc cref="MeshExtension.AsReadable(IndexBufferBinding, IServiceRegistry, out IndexBufferHelper, out int)"/>
public IndexBufferHelper(IndexBufferBinding binding, byte[] dataOuter, out int count)
{
if (dataOuter.Length < binding.Offset + binding.Count * (binding.Is32Bit ? 4 : 2))
throw new ArgumentException($"Binding describes an array larger than {nameof(dataOuter)} ({dataOuter.Length} < {binding.Offset} + {binding.Count} * {(binding.Is32Bit ? 4 : 2)})");
DataOuter = dataOuter;
Binding = binding;
count = Binding.Count;
}
/// <summary>
/// Branch to read the buffer as a 16 or 32 bit buffer, does not allocate
/// </summary>
/// <example>
/// <code>
/// if (Is32Bit(out var d32, out var d16))
/// {
/// foreach (var value in d32)
/// {
/// // Your logic for 32 bit
/// }
/// }View on GitHub (pinned to 96fad776d2)