stride3d/stride · error · InvalidOperationException

Invalid swizzle for scalar type

Error message

Invalid swizzle for scalar type

What it means

ApplyScalarSwizzles builds a vector by repeating a scalar value for each swizzle index. HLSL semantics allow repeating a scalar (any swizzle like .xxx works), but this implementation requires every index to be exactly 0; if any swizzle index is non-zero on a scalar it throws InvalidOperationException.

Solutions

  1. Fix the shader so the value is a vector before swizzling (construct a vector explicitly)
  2. Use only the x component when replicating a scalar: s.xxxx instead of s.yyyy
  3. Verify the symbol's inferred type is a vector, not a scalar
  4. Update builder to treat scalar broadcast as always valid per HLSL rules

Example fix

// before (HLSL)
float s = 1.0;
float2 v = s.yx;
// after
float s = 1.0;
float2 v = float2(s, s); // or s.xx
Defensive patterns

Strategy: type-guard

Validate before calling

// Scalars can only be replicated via index 0 (x)
if (targetType is ScalarType && swizzle.Indices.Any(i => i != 0))
    throw new ShaderSemanticException("Scalar swizzle components must be 'x'");

Type guard

bool IsValidScalarSwizzle(ReadOnlySpan<int> idx) { foreach (var i in idx) if (i != 0) return false; return idx.Length > 0; }

Try / catch

try { var r = ApplySwizzles(context, scalarValue, swizzle); }
catch (InvalidOperationException ex) when (ex.Message == "Invalid swizzle for scalar type") { throw new ShaderSemanticException("Cannot swizzle scalar with non-x components", ex); }

Prevention

When it happens

Trigger: Swizzling a scalar value with an index other than 0 (e.g. s.y or s.zw) reaching ApplySwizzles -> ApplyScalarSwizzles; swizzleIndices[j] != 0 for some j.

Common situations: Shader code that treats a float as if it were a vector, e.g. float f = 1.0; float2 v = f.yz; or frontend mislabeling a vector as scalar.

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/1df88b2b59dee129. Report an issue: GitHub.

Appendix: source

Thrown at sources/shaders/Stride.Shaders.Parsers/Spirv/Building/Builder.Expressions.cs:46

    {
        var valueType = context.ReverseTypes[value.TypeId];
        return valueType switch
        {
            ScalarType s => ApplyScalarSwizzles(context, value, s, swizzleIndices),
            VectorType v => ApplyVectorSwizzles(context, value, v, swizzleIndices),
            _ => throw new NotSupportedException($"Unsupported type for swizzle: {valueType}"),
        };
    }

    public (SpirvValue, SymbolType) ApplyScalarSwizzles(SpirvContext context, SpirvValue value, ScalarType s, Span<int> swizzleIndices)
    {
        var resultType = new VectorType(s, swizzleIndices.Length);

        Span<int> constructIndices = stackalloc int[swizzleIndices.Length];
        for (int j = 0; j < constructIndices.Length; ++j)
        {
            if (swizzleIndices[j] != 0)
                throw new InvalidOperationException("Invalid swizzle for scalar type");

            constructIndices[j] = value.Id;
        }

        SpirvValue result;
        var construct = InsertData(new OpCompositeConstruct(context.GetOrRegister(resultType), context.Bound++, new(constructIndices)));
        result = new(construct);
        return (result, resultType);
    }

    public (SpirvValue, SymbolType) ApplyVectorSwizzles(SpirvContext context, SpirvValue value, VectorType v, Span<int> swizzleIndices)
    {
        for (int j = 0; j < swizzleIndices.Length; ++j)
        {
            if (swizzleIndices[j] >= v.Size)
                throw new InvalidOperationException("Invalid swizzle for vector type");
        }

View on GitHub (pinned to 96fad776d2)