{"record":{"id":"1c672f5a4f02da68","repo":"stride3d/stride","slug":"can-t-process-constant-i-data-idresult","errorCode":null,"errorMessage":"Can't process constant {i.Data.IdResult}","messagePattern":"Can't process constant (.+?)","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"sources/shaders/Stride.Shaders.Parsers/Spirv/Building/Context.Constants.cs","lineNumber":60,"sourceCode":"        throw new Exception(\"Cannot find constant instruction for id \" + constantId);\n    }\n\n    public bool TryGetConstantValue(int constantId, [MaybeNullWhen(false)] out object value, out int typeId)\n    {\n        if (Buffer.TryGetInstructionById(constantId, out var constant))\n        {\n            return TryGetConstantValue(constant, out value, out typeId);\n        }\n\n        typeId = 0;\n        value = null;\n        return false;\n    }\n\n    public object ResolveConstantValue(OpDataIndex i)\n    {\n        if (!TryGetConstantValue(i, out var value, out _))\n            throw new InvalidOperationException($\"Can't process constant {i.Data.IdResult}\");\n\n        return value;\n    }\n\n    // 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.\n    public bool TryGetConstantValue(OpDataIndex i, [MaybeNullWhen(false)] out object value, out int typeId)\n    {\n        typeId = 0;\n        value = null;\n\n        // Check for unresolved values\n        if (i.Op == Specification.Op.OpGenericParameterSDSL || i.Op == Specification.Op.OpGenericReferenceSDSL)\n        {\n            return false;\n        }\n\n        if (i.Op == Specification.Op.OpConstantStringSDSL)\n        {","sourceCodeStart":42,"sourceCodeEnd":78,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/shaders/Stride.Shaders.Parsers/Spirv/Building/Context.Constants.cs#L42-L78","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nvar v = context.ResolveConstantValue(opDataIndex); // InvalidOperationException during generic pass\n// after\nif (context.TryGetConstantValue(opDataIndex, out var v, out var typeId)) { /* use v */ } else { /* defer */ }","handlingStrategy":"validation","validationCode":"if (!context.TryGetConstantValue(opDataIndex, out var v, out var typeId)) { DeferEvaluation(opDataIndex); return; }","typeGuard":null,"tryCatchPattern":"try { value = context.ResolveConstantValue(i); } catch (InvalidOperationException ex) when (ex.Message.StartsWith(\"Can't process constant\")) { DeferEvaluation(i); }","preventionTips":["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"],"tags":["spirv","constant","generics","invalid-state"],"backgroundTag":"invalid-state-transition","analyzedSha":"96fad776d210c221682aac1ccdf4c79dc046fc38","analyzedAt":"2026-09-14T02:59:31.279Z","contentChangedAt":"2026-09-14T02:59:31.279Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}