{"record":{"id":"a02f0446fc7988f0","repo":"stride3d/stride","slug":"binding-describes-an-array-larger-than-dataouter-dataouter","errorCode":null,"errorMessage":"Binding describes an array larger than dataOuter ({dataOuter.Length} < {binding.Offset} + {binding.Count} * {(binding.Is32Bit ? 4 : 2)})","messagePattern":"Binding describes an array larger than dataOuter \\((.+?) < (.+?) \\+ (.+?) \\* (.+?)\\)","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"sources/engine/Stride.Graphics/IndexBufferHelper.cs","lineNumber":43,"sourceCode":"    public readonly byte[] DataOuter;\n    public readonly IndexBufferBinding Binding;\n\n    /// <summary>\n    /// Effective index buffer, handles the binding offset\n    /// </summary>\n    public Span<byte> DataInner => DataOuter.AsSpan(Binding.Offset, Binding.Count * (Binding.Is32Bit ? 4 : 2));\n\n    /// <inheritdoc cref=\"MeshExtension.AsReadable(IndexBufferBinding, IServiceRegistry, out IndexBufferHelper, out int)\"/>\n    public IndexBufferHelper(IndexBufferBinding binding, IServiceRegistry services, out int count) \n        : this(binding, MeshExtension.FetchBufferContentOrThrow(binding.Buffer, services), out count)\n    {\n    }\n\n    /// <inheritdoc cref=\"MeshExtension.AsReadable(IndexBufferBinding, IServiceRegistry, out IndexBufferHelper, out int)\"/>\n    public IndexBufferHelper(IndexBufferBinding binding, byte[] dataOuter, out int count)\n    {\n        if (dataOuter.Length < binding.Offset + binding.Count * (binding.Is32Bit ? 4 : 2))\n            throw new ArgumentException($\"Binding describes an array larger than {nameof(dataOuter)} ({dataOuter.Length} < {binding.Offset} + {binding.Count} * {(binding.Is32Bit ? 4 : 2)})\");\n\n        DataOuter = dataOuter;\n        Binding = binding;\n        count = Binding.Count;\n    }\n\n    /// <summary>\n    /// Branch to read the buffer as a 16 or 32 bit buffer, does not allocate\n    /// </summary>\n    /// <example>\n    /// <code>\n    /// if (Is32Bit(out var d32, out var d16))\n    /// {\n    ///     foreach (var value in d32)\n    ///     {\n    ///         // Your logic for 32 bit\n    ///     }\n    /// }","sourceCodeStart":25,"sourceCodeEnd":61,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/engine/Stride.Graphics/IndexBufferHelper.cs#L25-L61","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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)."],"exampleFix":"// before\nvar helper = new IndexBufferHelper(binding, truncatedData, out var count);\n// after\nint required = binding.Offset + binding.Count * (binding.Is32Bit ? 4 : 2);\nif (data.Length < required) throw new InvalidOperationException($\"need {required} bytes, got {data.Length}\");\nvar helper = new IndexBufferHelper(binding, data, out var count);","handlingStrategy":"validation","validationCode":"int required = binding.Offset + binding.Count * (binding.Is32Bit ? 4 : 2);\nif (dataOuter == null || dataOuter.Length < required)\n    throw new InvalidOperationException($\"Index data too small: need {required}, have {dataOuter?.Length ?? 0}\");","typeGuard":"bool FitsBinding(IndexBufferBinding b, byte[] d) => d != null && d.Length >= b.Offset + b.Count * (b.Is32Bit ? 4 : 2);","tryCatchPattern":"try { var helper = new IndexBufferHelper(binding, data, out var count); }\ncatch (ArgumentException ex) { log.Error(\"index buffer data truncated\", ex); }","preventionTips":["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"],"tags":["csharp","graphics","meshes"],"backgroundTag":"invalid-argument-format","analyzedSha":"96fad776d210c221682aac1ccdf4c79dc046fc38","analyzedAt":"2026-09-14T02:59:31.279Z","contentChangedAt":"2026-09-14T02:59:31.279Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}