{"record":{"id":"fe1732a7fa3ccedd","repo":"stride3d/stride","slug":"couldn-t-handle-operand-logop","errorCode":null,"errorMessage":"Couldn't handle operand {logOp}","messagePattern":"Couldn't handle operand (.+?)","errorType":"exception","errorClass":"NotImplementedException","httpStatus":null,"severity":"error","filePath":"sources/shaders/Stride.Shaders.Spirv/Parsing/OpDataEnumerator.cs","lineNumber":118,"sourceCode":"                    operands[pid] switch\n                    {\n                        { Kind: OperandKind.PairIdRefIdRef or OperandKind.PairIdRefLiteralInteger or OperandKind.PairLiteralIntegerIdRef } => (wid + 2, oid, pid + 1, startOperand),\n                        { Kind: OperandKind.LiteralString } => (wid + Operands[wid..].LengthOfString(), oid, pid + 1, startOperand),\n                        { Kind: _ } => (wid + 1, oid, pid + 1, startOperand)\n                    },\n                { Quantifier: OperandQuantifier.One, Kind: OperandKind.PairIdRefIdRef or OperandKind.PairIdRefLiteralInteger or OperandKind.PairLiteralIntegerIdRef }\n                    => (wid + 2, oid + 1, -1, -1),\n                { Quantifier: OperandQuantifier.One, Kind: OperandKind.LiteralString } => (wid + Operands[wid..].LengthOfString(), oid + 1, -1, -1),\n                { Quantifier: OperandQuantifier.One, Kind: _ } => (wid + 1, oid + 1, -1, -1),\n                { Quantifier: OperandQuantifier.ZeroOrOne, Kind: OperandKind.PairIdRefIdRef or OperandKind.PairIdRefLiteralInteger or OperandKind.PairLiteralIntegerIdRef }\n                    => (wid + (wid < Operands.Length - 2 ? 2 : 0), oid + (wid < Operands.Length - 2 ? 1 : 0), -1, -1),\n                { Quantifier: OperandQuantifier.ZeroOrOne, Kind: OperandKind.LiteralString }\n                    => (wid + (wid < Operands.Length - 1 ? Operands[wid..].LengthOfString() : 0), oid + (wid < Operands.Length ? 1 : 0), -1, -1),\n                { Quantifier: OperandQuantifier.ZeroOrOne, Kind: _ }\n                    => (wid + (wid < Operands.Length ? 1 : 0), oid + (wid < Operands.Length ? 1 : 0), -1, -1),\n                { Quantifier: OperandQuantifier.ZeroOrMore }\n                    => (wid < Operands.Length - 1 ? Operands.Length : wid, oid + (wid < Operands.Length - 1 ? 0 : 1), -1, -1),\n                _ => throw new NotImplementedException($\"Couldn't handle operand {logOp}\")\n            };\n            wid = newWid;\n            oid = newOid;\n            pid = newPid;\n            // Reasons to return false : \n            // - no operands left\n            // - current operand has no kind (i.e. None)\n            return !(wid >= Operands.Length || oid >= logicalOperands.Count);\n\n        }\n    }\n\n    public SpvOperand ParseCurrent()\n    {\n        var logOp = logicalOperands[oid];\n\n        return logOp switch\n        {","sourceCodeStart":100,"sourceCodeEnd":136,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/shaders/Stride.Shaders.Spirv/Parsing/OpDataEnumerator.cs#L100-L136","documentation":"OpDataEnumerator.MoveNext advances word/operand/pattern indices per the SPIR-V grammar's operand quantifiers (One, ZeroOrOne, ZeroOrMore). The switch covers all quantifier kinds it knows; an operand shape not in the table hits the throw. This indicates either an unhandled combination of Quantifier and operand-position state or corrupted/unknown operand metadata.","triggerScenarios":"Iterating operands of an instruction whose operand descriptor has a Quantifier/Kind combination not covered by the MoveNext switch — e.g. ZeroOrMore appearing not-last, or unexpected logOp state — while consuming Op instruction words.","commonSituations":"Parsing SPIR-V from a newer grammar version (new operand kinds in spirv.core.grammar.json) than the library's embedded OpData tables; malformed/custom instruction streams; regenerated operand tables missing a case.","solutions":["Log logOp (name, quantifier, kind) at the throw site to identify the unhandled combination and add a matching switch arm.","Update the library's operand grammar tables to match the SPIR-V version of the module being parsed.","Validate the input SPIR-V with spirv-val to rule out a malformed module driving the enumerator off-spec.","As a workaround, parse the failing opcode manually instead of via OpDataEnumerator."],"exampleFix":"// before\n_ => throw new NotImplementedException($\"Couldn't handle operand {logOp}\")\n// after\n{ Quantifier: OperandQuantifier.ZeroOrMore, Kind: OperandKind.LiteralString } => /* handle strings */,\n_ => throw new NotImplementedException($\"Couldn't handle operand {logOp}\")","handlingStrategy":"try-catch","validationCode":"// validate the module first with spirv-val (external) and check opcode support:\nif (!opData.KnownOpcodes.Contains((Op)words[0] & 0xFFFF)) throw new NotSupportedException(\"Unknown opcode before enumeration\");","typeGuard":"null","tryCatchPattern":"try { while (enum.MoveNext()) ProcessCurrent(); }\ncatch (NotImplementedException ex) when (ex.Message.StartsWith(\"Couldn't handle operand\")) { /* fall back to manual parsing of this opcode; log the operand descriptor */ }","preventionTips":["Keep the library's grammar tables in sync with the SPIR-V version your modules use.","Run spirv-val on input modules before parsing.","Log the failing opcode/operand descriptor to add missing switch arms quickly."],"tags":["spirv","parsing","grammar","quantifier"],"backgroundTag":"method-not-implemented","analyzedSha":"96fad776d210c221682aac1ccdf4c79dc046fc38","analyzedAt":"2026-09-14T02:59:31.279Z","contentChangedAt":"2026-09-14T02:59:31.279Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}