stride3d/stride · error · NotImplementedException

params of strings is not yet implemented

Error message

params of strings is not yet implemented

What it means

OpDataEnumerator.ParseCurrent handles ZeroOrMore variadic operands generically (consume remaining words) and Pair* variadics (2 words each), but a ZeroOrMore LiteralString operand requires variable-length string decoding per repetition, which is not implemented — so it throws plain Exception. An instruction whose grammar has a trailing variadic list of strings (or an optional string that may repeat) hits this.

Solutions

  1. Identify the opcode (logOp.Name) hitting this path and parse its string list manually outside OpDataEnumerator.
  2. Add an arm consuming words until the string length encoding ends for each repetition, mirroring the LiteralString single-value logic.
  3. Update the grammar tables to avoid exposing ZeroOrMore LiteralString, or contribute the missing implementation upstream to Stride.
  4. Check the module producer: if this opcode is optional, strip/avoid it so the enumerator never encounters it.

Example fix

// before
{ Quantifier: OperandQuantifier.ZeroOrMore, Kind: OperandKind.LiteralString }
    => throw new Exception("params of strings is not yet implemented"),
// after
{ Quantifier: OperandQuantifier.ZeroOrMore, Kind: OperandKind.LiteralString }
    => new(logOp.Name, OperandKind.LiteralString, OperandQuantifier.ZeroOrMore, Operands.Slice(wid, Operands[wid..].LengthOfString()), wid),
Defensive patterns

Strategy: fallback

Validate before calling

// detect the unsupported shape before iterating:
if (logOp.Quantifier == OperandQuantifier.ZeroOrMore && logOp.Kind == OperandKind.LiteralString)
    ParseStringsManually(operands);

Type guard

static bool IsVariadicStrings(OperandDescriptor op) =>
    op.Quantifier == OperandQuantifier.ZeroOrMore && op.Kind == OperandKind.LiteralString;

Try / catch

try { var operand = enumerator.Current; }
catch (Exception ex) when (ex.Message.Contains("params of strings is not yet implemented")) { /* manual: consume words until length-prefixed string ends, repeat until words exhausted */ }

Prevention

When it happens

Trigger: Parsing an instruction whose operand descriptor is { Quantifier: ZeroOrMore, Kind: LiteralString } while iterating with OpDataEnumerator/Current — e.g. opcodes whose grammar defines a variadic sequence of literal strings.

Common situations: Extended instruction-set or debug opcodes with repeating string operands; custom/extension SPIR-V instructions; modules generated by tools emitting unusual operand layouts.

Related errors


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

Appendix: source

Thrown at sources/shaders/Stride.Shaders.Spirv/Parsing/OpDataEnumerator.cs:160

                { Name: string n, Kind: OperandKind k } when k.ToString().StartsWith("Pair") => new(n, k, logOp.Quantifier ?? OperandQuantifier.One, Operands.Slice(wid, 2), wid),
                { Name: string n, Kind: OperandKind.LiteralString } => new(n, OperandKind.LiteralString, logOp.Quantifier ?? OperandQuantifier.One, Operands.Slice(wid, Operands[wid..].LengthOfString()), wid),
                { Name: string n, Kind: OperandKind k } => new(n, k, logOp.Quantifier ?? OperandQuantifier.One, Operands.Slice(wid, 1), wid),
                _ => throw new NotImplementedException($"Couldn't handle operand kind {logOp.Kind}")
            },
            { Quantifier: OperandQuantifier.One, Kind: OperandKind.PairIdRefIdRef or OperandKind.PairIdRefLiteralInteger or OperandKind.PairLiteralIntegerIdRef } l
                => new(logOp.Name, logOp.Kind ?? OperandKind.None, logOp.Quantifier ?? OperandQuantifier.One, Operands.Slice(wid, 2), wid),
            { Quantifier: OperandQuantifier.One, Kind: OperandKind.LiteralString } => new(logOp.Name, OperandKind.LiteralString, logOp.Quantifier ?? OperandQuantifier.One, Operands.Slice(wid, Operands[wid..].LengthOfString()), wid),
            { Quantifier: OperandQuantifier.One, Kind: _ } => new(logOp.Name, logOp.Kind ?? OperandKind.None, logOp.Quantifier ?? OperandQuantifier.One, Operands.Slice(wid, 1), wid),
            { Quantifier: OperandQuantifier.ZeroOrOne, Kind: OperandKind.PairIdRefIdRef or OperandKind.PairIdRefLiteralInteger or OperandKind.PairLiteralIntegerIdRef }
                => new(logOp.Name, logOp.Kind ?? OperandKind.None, logOp.Quantifier ?? OperandQuantifier.One, Operands.Slice(wid, 2), wid),
            { Quantifier: OperandQuantifier.ZeroOrOne, Kind: OperandKind.LiteralString }
                => new(logOp.Name, OperandKind.LiteralString, logOp.Quantifier ?? OperandQuantifier.One, Operands.Slice(wid, Operands[wid..].LengthOfString()), wid),
            { Quantifier: OperandQuantifier.ZeroOrOne, Kind: _ }
                => new(logOp.Name, logOp.Kind ?? OperandKind.None, logOp.Quantifier ?? OperandQuantifier.One, wid < Operands.Length ? Operands.Slice(wid, 1) : []),
            { Quantifier: OperandQuantifier.ZeroOrMore, Kind: OperandKind.PairIdRefIdRef or OperandKind.PairIdRefLiteralInteger or OperandKind.PairLiteralIntegerIdRef }
                => new(logOp.Name, logOp.Kind ?? OperandKind.None, logOp.Quantifier ?? OperandQuantifier.One, wid < Operands.Length ? Operands[wid..] : [], wid),
            { Quantifier: OperandQuantifier.ZeroOrMore, Kind: OperandKind.LiteralString }
                => throw new Exception("params of strings is not yet implemented"),
            { Quantifier: OperandQuantifier.ZeroOrMore, Kind: _ }
                => new(logOp.Name, logOp.Kind ?? OperandKind.None, logOp.Quantifier ?? OperandQuantifier.One, wid < Operands.Length ? Operands[wid..] : [], wid),
            _ => throw new NotImplementedException()

        };
    }

}

View on GitHub (pinned to 96fad776d2)