{"record":{"id":"b0ee58c0711b0f60","repo":"stride3d/stride","slug":"can-t-parse-generic-value","errorCode":null,"errorMessage":"Can't parse generic value","messagePattern":"Can't parse generic value","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"sources/shaders/Stride.Shaders.Parsers/Spirv/Building/Builder.Class.cs","lineNumber":300,"sourceCode":"                    value = genericValue;\n                    return true;\n                default:\n                    throw new NotImplementedException();\n            }\n        }\n\n        public override bool ResolveGenericValueInBuffer(SymbolType genericParameterType, string genericParameterName, int genericIndex, SpirvContext context, ref int instructionIndex, out string textValue)\n        {\n            var genericParameter = (OpGenericParameterSDSL)context[instructionIndex];\n            var genericValue = genericValues![genericIndex];\n            textValue = genericValue;\n            switch (genericParameterType)\n            {\n                case ScalarType or VectorType:\n                    var scanner = new Scanner(textValue);\n                    ParseResult pr = new ParseResult();\n                    if (!ExpressionParser.Expression(ref scanner, pr, out var expression))\n                        throw new InvalidOperationException(\"Can't parse generic value\");\n                    var localContext = new SpirvContext();\n                    var result = expression.CompileConstantValue(new SymbolTable(localContext, null!), localContext, genericParameterType);\n                    context.RemoveAt(instructionIndex);\n                    context.InsertWithoutDuplicates(ref instructionIndex, genericParameter.ResultId, localContext.GetBuffer());\n                    return true;\n                case GenericParameterType g:\n                    context.Replace(instructionIndex++, new OpConstantStringSDSL(genericParameter.ResultId, genericValue));\n                    return true;\n                default:\n                    throw new NotImplementedException();\n            }\n        }\n    }\n\n    /// <summary>\n    /// Instantiate generics using another buffer for the shader constants. If a context is specified, constants will be imported there, otherwise inside the generic shader being instantiated.\n    /// </summary>\n    class GenericResolverFromInstantiatingBuffer(ShaderClassInstantiation classSource, ResolveStep resolveStep, SpirvContext declaringContext) : GenericResolver","sourceCodeStart":282,"sourceCodeEnd":318,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/shaders/Stride.Shaders.Parsers/Spirv/Building/Builder.Class.cs#L282-L318","documentation":"ResolveGenericValueInBuffer re-parses a generic argument's text value through the SDSL ExpressionParser when the parameter is a ScalarType or VectorType. If ExpressionParser.Expression fails on the text, the library throws InvalidOperationException(\"Can't parse generic value\") because the string is not a valid constant expression.","triggerScenarios":"Passing a generic argument string (e.g. from GetOrLoadShader genericValues) that the SDSL ExpressionParser cannot parse as a constant expression — malformed syntax, unsupported tokens, empty text.","commonSituations":"Loading a cached shader with generic values like `float2(1,2` (unbalanced), a named identifier instead of a literal, or locale-formatted numbers ('1,5' or '1.5f.3'); macros expanding into invalid expressions.","solutions":["Fix the generic value string so it is a valid SDSL constant expression (e.g. `1.0`, `float2(1.0, 2.0)`).","Ensure numeric values are serialized with InvariantCulture when building the generic argument strings.","Log/inspect the offending textValue and validate it with the Scanner/ExpressionParser before calling the builder."],"exampleFix":"// before\ngenericValues[i] = value.ToString();\n// after\ngenericValues[i] = Convert.ToString(value, CultureInfo.InvariantCulture);","handlingStrategy":"validation","validationCode":"var scanner = new Scanner(textValue);\nif (!ExpressionParser.Expression(ref scanner, new ParseResult(), out _))\n    throw new ArgumentException($\"'{textValue}' is not a valid SDSL constant expression\");","typeGuard":null,"tryCatchPattern":"try { builder.ResolveGenericValueInBuffer(type, name, index, context, ref idx, value); }\ncatch (InvalidOperationException ex) when (ex.Message == \"Can't parse generic value\") { throw new FormatException($\"Invalid generic value '{value}' for '{name}'\", ex); }","preventionTips":["Serialize generic values with CultureInfo.InvariantCulture","Validate generic strings with the SDSL Scanner/ExpressionParser before passing them","Avoid locale-dependent decimal separators in generated shader code"],"tags":["sdsl","parser","generics","invalid-argument-format"],"backgroundTag":"invalid-argument-format","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"}