stride3d/stride · error · InvalidOperationException
Can't parse generic value
Error message
Can't parse generic value
What it means
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.
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.
Example fix
// before genericValues[i] = value.ToString(); // after genericValues[i] = Convert.ToString(value, CultureInfo.InvariantCulture);
Defensive patterns
Strategy: validation
Validate before calling
var scanner = new Scanner(textValue);
if (!ExpressionParser.Expression(ref scanner, new ParseResult(), out _))
throw new ArgumentException($"'{textValue}' is not a valid SDSL constant expression"); Try / catch
try { builder.ResolveGenericValueInBuffer(type, name, index, context, ref idx, value); }
catch (InvalidOperationException ex) when (ex.Message == "Can't parse generic value") { throw new FormatException($"Invalid generic value '{value}' for '{name}'", ex); } Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- Can't have member variables with generic shader types
- Cannot use as a list of digit
- Exception of type 'System.NotImplementedException' was…
- Exception of type 'System.NotImplementedException' was…
- Assign back to matrix swizzle is not implemented yet
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/b0ee58c0711b0f60.
Report an issue: GitHub.
Appendix: source
Thrown at sources/shaders/Stride.Shaders.Parsers/Spirv/Building/Builder.Class.cs:300
value = genericValue;
return true;
default:
throw new NotImplementedException();
}
}
public override bool ResolveGenericValueInBuffer(SymbolType genericParameterType, string genericParameterName, int genericIndex, SpirvContext context, ref int instructionIndex, out string textValue)
{
var genericParameter = (OpGenericParameterSDSL)context[instructionIndex];
var genericValue = genericValues![genericIndex];
textValue = genericValue;
switch (genericParameterType)
{
case ScalarType or VectorType:
var scanner = new Scanner(textValue);
ParseResult pr = new ParseResult();
if (!ExpressionParser.Expression(ref scanner, pr, out var expression))
throw new InvalidOperationException("Can't parse generic value");
var localContext = new SpirvContext();
var result = expression.CompileConstantValue(new SymbolTable(localContext, null!), localContext, genericParameterType);
context.RemoveAt(instructionIndex);
context.InsertWithoutDuplicates(ref instructionIndex, genericParameter.ResultId, localContext.GetBuffer());
return true;
case GenericParameterType g:
context.Replace(instructionIndex++, new OpConstantStringSDSL(genericParameter.ResultId, genericValue));
return true;
default:
throw new NotImplementedException();
}
}
}
/// <summary>
/// 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.
/// </summary>
class GenericResolverFromInstantiatingBuffer(ShaderClassInstantiation classSource, ResolveStep resolveStep, SpirvContext declaringContext) : GenericResolverView on GitHub (pinned to 96fad776d2)