{"record":{"id":"4d158f7858dcef62","repo":"stride3d/stride","slug":"cannot-determine-type-for-emitted-instruction-instructionid","errorCode":null,"errorMessage":"Cannot determine type for emitted instruction {instructionId}","messagePattern":"Cannot determine type for emitted instruction (.+?)","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"sources/shaders/Stride.Shaders.Parsers/Core/ConstantExpression.cs","lineNumber":42,"sourceCode":"    public abstract bool TryEvaluate(out object? value);\n\n    /// <summary>\n    /// Replace GenericParamExpr nodes matching the given declaringClass with resolved values.\n    /// Returns this if no substitution occurred.\n    /// </summary>\n    public virtual ConstantExpression Substitute(string declaringClass, ConstantExpression[] args) => this;\n\n    /// <summary>\n    /// Look up the ResultType of an emitted instruction by its ID.\n    /// </summary>\n    protected static int GetEmittedTypeId(SpirvContext context, int instructionId)\n    {\n        if (context.GetBuffer().TryGetInstructionById(instructionId, out var inst))\n        {\n            if (inst.Data.IdResultType is int typeId)\n                return typeId;\n        }\n        throw new InvalidOperationException($\"Cannot determine type for emitted instruction {instructionId}\");\n    }\n\n    /// <summary>\n    /// Emit the expression into a temporary standalone SpirvBuffer.\n    /// Used when the expression needs to be imported into another context via InsertWithoutDuplicates.\n    /// </summary>\n    public SpirvBuffer EmitToBuffer()\n    {\n        var tempContext = new SpirvContext();\n        var resultId = Emit(tempContext);\n        return SpirvContext.ExtractConstantFromBuffer(resultId, tempContext.GetBuffer());\n    }\n\n    /// <summary>\n    /// Create a ConstantExpression from a concrete runtime value.\n    /// </summary>\n    public static ConstantExpression FromValue(object value) => value switch\n    {","sourceCodeStart":24,"sourceCodeEnd":60,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/shaders/Stride.Shaders.Parsers/Core/ConstantExpression.cs#L24-L60","documentation":"ConstantExpression.GetEmittedTypeId throws InvalidOperationException when the SPIR-V buffer has no instruction matching the given instructionId, so the emitted type cannot be determined. It's used by operandTypeId/resultTypeId to resolve result-type IDs of emitted instructions.","triggerScenarios":"Querying the type of an instruction ID that was never emitted into the current SpirvContext buffer — e.g. an instruction emitted into a standalone buffer while the context queried is a different one, or a stale/incorrect ID passed in.","commonSituations":"SPIR-V codegen where a constant/expression was emitted into a temporary buffer (Emit-to-temp path) but its ID is resolved against the wrong buffer; internal codegen bugs after refactoring instruction emission.","solutions":["Ensure the instruction was emitted into the same SpirvBuffer/SpirvContext being queried (insert temporary buffers via InsertWithoutDuplicates first).","Verify the instructionId corresponds to a valid result ID in the buffer (log the ID range).","If this arises from library code, step through emission order — the instruction may need emitting before its type is queried."],"exampleFix":"// before\nvar typeId = ConstantExpression.GetEmittedTypeId(context, newId); // newId from temp buffer\n// after\ncontext.GetBuffer().InsertWithoutDuplicates(tempBuffer); // make instruction visible first\nvar typeId = ConstantExpression.GetEmittedTypeId(context, newId);","handlingStrategy":"try-catch","validationCode":"if (!context.GetBuffer().TryGetInstructionById(instructionId, out _))\n    throw new InvalidOperationException($\"Instruction {instructionId} not emitted into this context\");","typeGuard":null,"tryCatchPattern":"try { typeId = GetEmittedTypeId(context, id); }\ncatch (InvalidOperationException ex) when (ex.Message.StartsWith(\"Cannot determine type\")) { /* insert buffer or fix emission order */ }","preventionTips":["Insert temporary emission buffers into the target context before resolving IDs","Never cache instruction IDs across different SpirvContexts","Emit an instruction before querying its result type"],"tags":["spirv","codegen","internal"],"backgroundTag":"internal-invariant-violation","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"}