stride3d/stride · error · ArgumentException

The 's offset and size makes it extend beyond the vertex…

Error message

The {nameof(VertexElement)}'s offset and size makes it extend beyond the vertex stride

What it means

Validate checks each element's offset plus its format size in bytes against the declared vertex stride. An element whose offset equals AppendAligned (not resolved here) or whose byte range runs past the stride is rejected with ArgumentException.

Solutions

  1. Increase the vertex stride to accommodate the largest offset + size
  2. Lower the element's offset so offset + Format.SizeInBytes <= vertexStride
  3. Use the append-aligned mechanism if supported, or compute offsets sequentially from Format.SizeInBytes

Example fix

// before
// stride = 16, element offset = 12, format R32G32B32A32 (16 bytes) => 28 > 16
// after
// stride = 32, or offset = 0 with 16-byte stride
Defensive patterns

Strategy: validation

Validate before calling

bool FitsInStride(VertexElement e, int offset, int stride) =>
    offset != VertexElement.AppendAligned && offset + e.Format.SizeInBytes <= stride;

Try / catch

try { VertexElementValidator.Validate(stride, elements); } catch (ArgumentException) { growStrideOrFixOffsets(); }

Prevention

When it happens

Trigger: Declaring an element with a hardcoded offset such that offset + Format.SizeInBytes > vertexStride; shrinking the stride after changing an element format without adjusting offsets.

Common situations: Manually laid-out vertex declarations where a Vector4 element starts near the end of the stride; changing an element from R32G32 to R32G32B32A32 without moving subsequent offsets.

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/5d80b0a3e08c6f11. Report an issue: GitHub.

Appendix: source

Thrown at sources/engine/Stride.Graphics/VertexElementValidator.cs:87

        for (int i = 0; i < overlapCheckArray.Length; i++)
            overlapCheckArray[i] = -1;

        int totalOffset = 0;
        for (int elementIndex = 0; elementIndex < elements.Length; elementIndex++)
        {
            // Compute the offset for this element
            int elementOffset = elements[elementIndex].AlignedByteOffset;
            if (elementOffset == VertexElement.AppendAligned)
            {
                elementOffset = elementIndex == 0 ? 0 : totalOffset + elements[elementIndex - 1].Format.SizeInBytes;
            }
            totalOffset = elementOffset;

            // Validate the element offset
            int typeSize = elements[elementIndex].Format.SizeInBytes;
            if (elementOffset == VertexElement.AppendAligned || (elementOffset + typeSize) > vertexStride)
            {
                throw new ArgumentException($"The {nameof(VertexElement)}'s offset and size makes it extend beyond the vertex stride", nameof(elements));
            }
            if ((elementOffset & 3) != 0)
            {
                throw new ArgumentException($"The offset of the {nameof(VertexElement)} is not a multiple of 4 bytes", nameof(elements));
            }

            // Check for duplicate semantic names and indices
            for (int i = 0; i < elementIndex; i++)
            {
                if (elements[elementIndex].SemanticName.Equals(elements[i].SemanticName) &&
                    elements[elementIndex].SemanticIndex == elements[i].SemanticIndex)
                {
                    throw new ArgumentException($"Duplicate {nameof(VertexElement)}s found with the same semantic name and index", nameof(elements));
                }
            }

            // Check for overlap with existing elements
            for (int i = elementOffset; i < (elementOffset + typeSize); i++)

View on GitHub (pinned to 96fad776d2)