stride3d/stride · error · ArgumentOutOfRangeException

indexCountArg must be >= 0

Error message

indexCountArg must be >= 0

What it means

A validation guard in VertexHelper.GenerateTangentBinormal: indexCountArg (the index count of the buffer used to generate tangents/binormals) is negative. Computing tangent frames iterates over indices; a negative count makes the operation meaningless and would cause invalid memory access, so the method throws an ArgumentOutOfRangeException before touching the buffers.

Solutions

  1. Pass the actual index count (e.g. indexBuffer.Length) instead of a computed/sentinel value.
  2. Fix the computation that yields the negative count.
  3. If there are truly no indices, pass IntPtr.Zero for indexData so the count is not required.

Example fix

// before
int indexCount = endIndex - startIndex; // -1 when indices missing
GenerateTangentBinormal(decl, ptr, count, 0, stride, indexPtr, true, indexCount);

// after
GenerateTangentBinormal(decl, ptr, count, 0, stride, indexPtr, true, indices.Length);
Defensive patterns

Strategy: validation

Validate before calling

if (indexData != IntPtr.Zero && indexCountArg < 0) throw new InvalidOperationException("indexCountArg must be >= 0 when an index buffer is supplied");

Type guard

bool IsValidIndexCount(nint indexData, int count) => indexData == IntPtr.Zero || count >= 0;

Try / catch

try { GenerateTangentBinormal(decl, ptr, count, 0, stride, indexPtr, true, indexCount); }
catch (ArgumentOutOfRangeException ex) { log.Error("Negative index count; use the real buffer length", ex); }

Prevention

When it happens

Trigger: Calling the IntPtr overload with indexData != IntPtr.Zero and a negative indexCountArg — e.g. an index buffer length computed to a negative value or a bad cast.

Common situations: Computing index count via subtraction/overflow; reusing a variable that was set to -1 as a sentinel; mismatch between indexData size and the count parameter.

Related errors


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

Appendix: source

Thrown at sources/engine/Stride.Graphics/VertexHelper.cs:237

        /// <summary>
        /// Generate Tangent BiNormal from an existing vertex/index buffer.
        /// </summary>
        /// <param name="vertexDeclaration">The vertex declaration of the vertex buffer passed by parameters.</param>
        /// <param name="vertexBufferData">The vertex buffer.</param>
        /// <param name="vertexCount">The vertex count.</param>
        /// <param name="vertexOffset">The vertex offset.</param>
        /// <param name="vertexStride">The vertex stride. If 0, It takes the stride from the vertex declaration</param>
        /// <param name="indexData">The index data.</param>
        /// <param name="is32BitIndex">if set to <c>true</c> [is32 bit index].</param>
        /// <param name="indexCountArg">The index count argument.</param>
        /// <returns>A new vertex buffer with its new layout.</returns>
        public static unsafe VertexTransformResult GenerateTangentBinormal(VertexDeclaration vertexDeclaration, IntPtr vertexBufferData, int vertexCount, int vertexOffset, int vertexStride, IntPtr indexData, bool is32BitIndex, int indexCountArg)
        {
            if (vertexDeclaration == null) throw new ArgumentNullException("vertexDeclaration");
            if (vertexBufferData == IntPtr.Zero) throw new ArgumentNullException("vertexBufferData");
            if (vertexCount <= 0) throw new ArgumentOutOfRangeException("vertexCount", "vertexCount must be > 0");
            if (vertexStride < 0) throw new ArgumentOutOfRangeException("vertexStride", "vertexStride must be >= 0");
            if (indexData != IntPtr.Zero && indexCountArg < 0) throw new ArgumentOutOfRangeException("indexCountArg", "indexCountArg must be >= 0");

            // Get the stride from the vertex declaration if necessary
            if (vertexStride == 0)
            {
                vertexStride = vertexDeclaration.VertexStride;
            }

            var indexBufferBinding = indexData;

            var oldVertexStride = vertexStride;
            var bufferData = vertexBufferData;

            // TODO: Usage index in key
            var offsetMapping = vertexDeclaration
                .EnumerateWithOffsets()
                .ToDictionary(x => x.VertexElement.SemanticAsText, x => x.Offset);

            var positionOffset = offsetMapping["POSITION"];

View on GitHub (pinned to 96fad776d2)