stride3d/stride · error · InvalidOperationException
Can't process constant {i.Data.IdResult}
Error message
Can't process constant {i.Data.IdResult} What it means
ResolveConstantValue is a throwing wrapper around TryGetConstantValue: when TryGetConstantValue returns false — meaning the constant's operands cannot yet be folded (e.g. operands are themselves unresolved, per the code comment about unresolved generics) or the instruction shape is unrecognized — it throws an InvalidOperationException naming the instruction's IdResult. It is for callers who know the constant must be resolvable at this point.
Solutions
- Call TryGetConstantValue first and only invoke ResolveConstantValue after generics are fully resolved.
- Defer constant evaluation until after generic substitution passes complete.
- Handle the constant kind in TryGetConstantValue (e.g. add OpConstantComposite support) if it is legitimately constant.
Example fix
// before
var v = context.ResolveConstantValue(opDataIndex); // InvalidOperationException during generic pass
// after
if (context.TryGetConstantValue(opDataIndex, out var v, out var typeId)) { /* use v */ } else { /* defer */ } Defensive patterns
Strategy: validation
Validate before calling
if (!context.TryGetConstantValue(opDataIndex, out var v, out var typeId)) { DeferEvaluation(opDataIndex); return; } Try / catch
try { value = context.ResolveConstantValue(i); } catch (InvalidOperationException ex) when (ex.Message.StartsWith("Can't process constant")) { DeferEvaluation(i); } Prevention
- Only call ResolveConstantValue after generic substitution completes
- Use the Try variant when generics may still be open
- Track which constants depend on generic parameters and evaluate them last
When it happens
Trigger: Calling ResolveConstantValue on an OpConstant (or derived op like OpBitcast/OpIAdd) whose operand ids cannot be resolved yet due to unresolved generic arguments, or whose opcode shape TryGetConstantValue does not handle.
Common situations: Evaluating constants during generic instantiation where the operand constant belongs to a not-yet-substituted generic parameter; composite constants (OpConstantComposite) that the fold logic does not decompose.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Cannot find instruction for id {constantId}
- Not enough generic parameters specified when instantiating {
- Exception of type 'System.NotImplementedException' was throw
- During mix phase, shaders generics are expected to be fully
- Generic argument {i} ({expr}) for {classSource.ClassName} co
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/1c672f5a4f02da68.
Report an issue: GitHub.
Appendix: source
Thrown at sources/shaders/Stride.Shaders.Parsers/Spirv/Building/Context.Constants.cs:60
throw new Exception("Cannot find constant instruction for id " + constantId);
}
public bool TryGetConstantValue(int constantId, [MaybeNullWhen(false)] out object value, out int typeId)
{
if (Buffer.TryGetInstructionById(constantId, out var constant))
{
return TryGetConstantValue(constant, out value, out typeId);
}
typeId = 0;
value = null;
return false;
}
public object ResolveConstantValue(OpDataIndex i)
{
if (!TryGetConstantValue(i, out var value, out _))
throw new InvalidOperationException($"Can't process constant {i.Data.IdResult}");
return value;
}
// Note: this will return false if constant can't be resolved yet (i.e. due to unresolved generics). If it is not meant to become a constant (even later), behavior is undefined.
public bool TryGetConstantValue(OpDataIndex i, [MaybeNullWhen(false)] out object value, out int typeId)
{
typeId = 0;
value = null;
// Check for unresolved values
if (i.Op == Specification.Op.OpGenericParameterSDSL || i.Op == Specification.Op.OpGenericReferenceSDSL)
{
return false;
}
if (i.Op == Specification.Op.OpConstantStringSDSL)
{View on GitHub (pinned to 96fad776d2)