stride3d/stride · error · InvalidOperationException

The vertex buffer must contain at least the TEXCOORD

Error message

The vertex buffer must contain at least the TEXCOORD

What it means

GenerateMultiTextureCoordinates cannot extend a vertex layout unless the source vertex buffer already has a TEXCOORD semantic; it needs the UV offset to locate existing coordinates and append additional UV sets after them. Stride throws InvalidOperationException when scanning the vertex elements finds no TEXCOORD channel (vertexUVOffset < 0).

Solutions

  1. Add a TextureCoordinateValue (TEXCOORD0) element to the vertex declaration before calling GenerateMultiTextureCoordinates.
  2. Initialize UVs in your geometry builder (e.g. MeshBuilder.AddTextureCoordinate) so the source buffer has a valid UV channel.
  3. If the mesh legitimately has no UVs, skip multi-texture-coordinate generation entirely.

Example fix

// before
var layout = VertexDescription.New<PositionNormal>();
var result = VertexHelper.GenerateMultiTextureCoordinates(layout, vertexData, 2);

// after
var layout = VertexDescription.New<PositionNormalTexture>();
var result = VertexHelper.GenerateMultiTextureCoordinates(layout, vertexData, 2);
Defensive patterns

Strategy: validation

Validate before calling

bool hasTexCoord = declaration.EnumerateWithOffsets()
    .Any(e => e.Element.SemanticName == "TEXCOORD");
if (!hasTexCoord) throw new InvalidOperationException("Vertex buffer needs TEXCOORD0 before generating multi texture coordinates");

Try / catch

try { var result = VertexHelper.GenerateMultiTextureCoordinates(decl, data, count); }
catch (InvalidOperationException ex) { log.Warn("Mesh has no UVs; skipping multi-UV generation", ex); }

Prevention

When it happens

Trigger: Calling VertexHelper.GenerateMultiTextureCoordinates with a VertexDeclaration/vertex buffer whose elements contain POSITION and NORMAL but no TEXCOORD0 element, so the computed vertexUVOffset stays -1.

Common situations: Building meshes procedurally from position-only data (collision shapes, particle geometry) then trying to add texture coordinate channels; forgetting to add TextureCoordinateValue to the vertex declaration when constructing geometry in code.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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

Appendix: source

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

            {
                var vertexElement = VertexElement.TextureCoordinate(i, DefaultUVFormat);
                var semantic = vertexElement.SemanticAsText;
                if (offsetMapping.TryGetValue(semantic, out int offset))
                {
                    if (vertexUVOffset < 0)
                    {
                        vertexUVOffset = offset;
                    }
                }
                else
                {
                    newVertexElements.Add(vertexElement);
                }
            }

            if (vertexUVOffset < 0)
            {
                throw new InvalidOperationException("The vertex buffer must contain at least the TEXCOORD");
            }

            var newVertexStride = vertexStride + newVertexElements.Count * newUvSize;
            var newVertexBuffer = new byte[newVertexStride * vertexCount];

            byte* oldBuffer = (byte*)vertexBufferData + vertexOffset;
            fixed (byte* newBuffer = newVertexBuffer)
            {
                var oldVertexOffset = 0;
                var newVertexOffset = 0;
                for (int i = 0; i < vertexCount; ++i)
                {
                    MemoryUtilities.CopyWithAlignmentFallback(newBuffer + newVertexOffset, oldBuffer + oldVertexOffset, (uint)vertexStride);

                    var textureCoord = *(Vector2*)&oldBuffer[oldVertexOffset + vertexUVOffset];
                    for (int j = 0; j < newVertexElements.Count; j++)
                    {
                        var target = ((Half2*)(&newBuffer[newVertexOffset + vertexStride + j * newUvSize]));

View on GitHub (pinned to 96fad776d2)