stride3d/stride · error · InvalidOperationException

: Expecting elements but got for type

Error message

{nameof(VectorLiteral)}: Expecting {totalCount} elements but got {elementIndex} for type {Type}

What it means

After flattening (including broadcast of a single value), VectorLiteral.CompileImpl verifies the collected element count equals the total count implied by the literal's type (vector size, matrix columns*rows, or array size). A mismatch means the initializer supplied the wrong number of elements, so compilation fails with this InvalidOperationException.

Solutions

  1. Count the initializer elements and match them exactly to the type's total element count
  2. Broadcast explicitly (repeat the value) instead of relying on implicit padding
  3. If the type changed, update the initializer list accordingly

Example fix

// before
float4 v = { 1.0, 2.0, 3.0 }; // 3 of 4
// after
float4 v = { 1.0, 2.0, 3.0, 4.0 };
Defensive patterns

Strategy: validation

Validate before calling

int expected = literal.Type switch {
    VectorType v => v.Size,
    MatrixType m => m.Columns * m.Rows,
    ArrayType a => a.Size,
    _ => throw new NotSupportedException() };
if (literal.Elements.Count != expected && literal.Elements.Count != 1)
    throw new InvalidOperationException($"Expecting {expected} elements but got {literal.Elements.Count}");

Try / catch

try { literal.Compile(context, builder); }
catch (InvalidOperationException ex) when (ex.Message.Contains("Expecting") && ex.Message.Contains("elements")) { /* fix initializer arity */ }

Prevention

When it happens

Trigger: An aggregate literal provides fewer or more scalar values than the target type requires, e.g. 3 values for a float4 or 12 values for a float4x4.

Common situations: Hand-written initializer lists with missing trailing elements; size changed in one place (type) but not the other (value list); matrix row/column confusion (float4x1 vs float1x4).

Related errors


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

Appendix: source

Thrown at sources/shaders/Stride.Shaders.Parsers/Parsing/SDSL/AST/Literals.cs:236

                    values[currentElementIndex] = builder.Convert(context, extractedValue, expectedElementType).Id;
                }
            }
            else if (Type is ArrayType arrayType)
            {
                values[elementIndex++] = builder.Convert(context, value, expectedElementType).Id;
            }
        }

        // Scalar splat: float3(x) means float3(x, x, x)
        if (elementIndex == 1 && totalCount > 1 && Type is VectorType or MatrixType)
        {
            for (int j = 1; j < totalCount; ++j)
                values[j] = values[0];
            elementIndex = totalCount;
        }

        if (elementIndex != totalCount)
            throw new InvalidOperationException($"{nameof(VectorLiteral)}: Expecting {totalCount} elements but got {elementIndex} for type {Type}");

        // Regroup by rows (if necessary, only for Matrix)
        int compositeSize = totalCount / compositeCount;
        for (int i = 0; i < compositeCount; ++i)
        {
            compositeValues[i] = Type switch
            {
                MatrixType m => builder.Insert(new OpCompositeConstruct(context.GetOrRegister(new VectorType(m.BaseType, compositeSize)), context.Bound++, [.. values.Slice(i * compositeSize, compositeSize)])).ResultId,
                VectorType v => values[i],
                ArrayType => values[i],
                _ => throw new NotSupportedException($"Unsupported composite type {Type} during regrouping"),
            };
        }

        var instruction = builder.Insert(new OpCompositeConstruct(context.GetOrRegister(Type), context.Bound++, [.. compositeValues]));
        return new(instruction.ResultId, instruction.ResultType);
    }
}

View on GitHub (pinned to 96fad776d2)