stride3d/stride · error · InvalidOperationException

Cannot determine type for emitted instruction

Error message

Cannot determine type for emitted instruction {instructionId}

What it means

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.

Solutions

  1. Ensure the instruction was emitted into the same SpirvBuffer/SpirvContext being queried (insert temporary buffers via InsertWithoutDuplicates first).
  2. Verify the instructionId corresponds to a valid result ID in the buffer (log the ID range).
  3. If this arises from library code, step through emission order — the instruction may need emitting before its type is queried.

Example fix

// before
var typeId = ConstantExpression.GetEmittedTypeId(context, newId); // newId from temp buffer
// after
context.GetBuffer().InsertWithoutDuplicates(tempBuffer); // make instruction visible first
var typeId = ConstantExpression.GetEmittedTypeId(context, newId);
Defensive patterns

Strategy: try-catch

Validate before calling

if (!context.GetBuffer().TryGetInstructionById(instructionId, out _))
    throw new InvalidOperationException($"Instruction {instructionId} not emitted into this context");

Try / catch

try { typeId = GetEmittedTypeId(context, id); }
catch (InvalidOperationException ex) when (ex.Message.StartsWith("Cannot determine type")) { /* insert buffer or fix emission order */ }

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14). Data as JSON: /api/errors/4d158f7858dcef62. Report an issue: GitHub.

Appendix: source

Thrown at sources/shaders/Stride.Shaders.Parsers/Core/ConstantExpression.cs:42

    public abstract bool TryEvaluate(out object? value);

    /// <summary>
    /// Replace GenericParamExpr nodes matching the given declaringClass with resolved values.
    /// Returns this if no substitution occurred.
    /// </summary>
    public virtual ConstantExpression Substitute(string declaringClass, ConstantExpression[] args) => this;

    /// <summary>
    /// Look up the ResultType of an emitted instruction by its ID.
    /// </summary>
    protected static int GetEmittedTypeId(SpirvContext context, int instructionId)
    {
        if (context.GetBuffer().TryGetInstructionById(instructionId, out var inst))
        {
            if (inst.Data.IdResultType is int typeId)
                return typeId;
        }
        throw new InvalidOperationException($"Cannot determine type for emitted instruction {instructionId}");
    }

    /// <summary>
    /// Emit the expression into a temporary standalone SpirvBuffer.
    /// Used when the expression needs to be imported into another context via InsertWithoutDuplicates.
    /// </summary>
    public SpirvBuffer EmitToBuffer()
    {
        var tempContext = new SpirvContext();
        var resultId = Emit(tempContext);
        return SpirvContext.ExtractConstantFromBuffer(resultId, tempContext.GetBuffer());
    }

    /// <summary>
    /// Create a ConstantExpression from a concrete runtime value.
    /// </summary>
    public static ConstantExpression FromValue(object value) => value switch
    {

View on GitHub (pinned to 96fad776d2)