stride3d/stride · error · InvalidOperationException

Exception of type 'System.InvalidOperationException' was…

Error message

Exception of type 'System.InvalidOperationException' was thrown.

What it means

ApplyVectorSwizzles handles a single-index swizzle by extracting one component; the multi-index path builds a composite. The final else throws a bare InvalidOperationException, representing an unhandled/unexpected swizzle case (e.g. zero-length swizzle) that fell through both branches.

Solutions

  1. Debug the upstream parser to find why a zero-length swizzle was produced
  2. Add a guard before calling ApplySwizzles to reject empty swizzle index spans
  3. Treat empty swizzle as identity (return the value unchanged) in the builder
  4. Enable logging of the offending expression/type to locate the source construct

Example fix

// before
public (SpirvValue, SymbolType) ApplyVectorSwizzles(...) { ... }
// after
if (swizzleIndices.Length == 0) return (value, (SymbolType)v); // identity fast-path before switch
Defensive patterns

Strategy: validation

Validate before calling

// Reject empty swizzles before calling the builder
if (swizzleIndices.Length == 0)
    throw new ShaderSemanticException("Empty swizzle expression");

Type guard

bool IsNonEmptySwizzle(ReadOnlySpan<int> idx) => idx.Length > 0;

Try / catch

try { var r = ApplySwizzles(context, value, swizzle); }
catch (InvalidOperationException ex) when (ex.Message is "" or "Exception of type 'System.InvalidOperationException' was thrown.") { Log.Error(ex, "Unhandled swizzle case (likely empty swizzle) for {Type}", context.ReverseTypes[value.TypeId]); throw; }

Prevention

When it happens

Trigger: ApplySwizzles calls ApplyVectorSwizzles with an empty (Length == 0) swizzle index span, so swizzleIndices.Length > 1 is false and the single-element path is also invalid, hitting the bare throw.

Common situations: Frontend/parser emitting a swizzle with no components (e.g. empty swizzle from an empty member-access token); corrupted AST or tokenization bug.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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

Appendix: source

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

        {
            // Apply swizzle
            var resultType = new VectorType(v.BaseType, swizzleIndices.Length);
            var shuffle = InsertData(new OpVectorShuffle(context.GetOrRegister(resultType), context.Bound++, value.Id, value.Id, new(swizzleIndices)));
            value = new(shuffle);

            return (value, resultType);
        }
        else if (swizzleIndices.Length == 1)
        {
            // Apply swizzle
            var resultType = v.BaseType;
            var extract = InsertData(new OpCompositeExtract(context.GetOrRegister(resultType), context.Bound++, value.Id, [swizzleIndices[0]]));
            value = new(extract);

            return (value, resultType);
        }
        else
            throw new InvalidOperationException();
    }

    public (SpirvValue, SymbolType) ApplyMatrixSwizzles(SpirvContext context, SpirvValue value, MatrixType m, Span<(int Column, int Row)> swizzles)
    {
        Span<int> elements = stackalloc int[swizzles.Length];
        for (var swizzleIndex = 0; swizzleIndex < swizzles.Length; swizzleIndex++)
        {
            var swizzle = swizzles[swizzleIndex];
            elements[swizzleIndex] = Insert(new OpCompositeExtract(context.GetOrRegister(m.BaseType), context.Bound++, value.Id, [swizzle.Column, swizzle.Row])).ResultId;
        }

        var resultType = m.BaseType.GetVectorOrScalar(swizzles.Length);
        value = swizzles.Length > 1
            ? new(InsertData(new OpCompositeConstruct(context.GetOrRegister(resultType), context.Bound++, [.. elements])))
            : new(elements[0], context.GetOrRegister(resultType));

        return (value, resultType);
    }

View on GitHub (pinned to 96fad776d2)