stride3d/stride · error · Exception

Instruction has no result id

Error message

Instruction has no result id

What it means

The implicit conversion Instruction -> IdRef requires the instruction to have a result id (ResultId). SPIR-V instructions like OpReturn, OpStore, or OpBranch produce no result, so ResultId is null and the conversion throws. This guards against treating a non-result instruction as a referenceable id.

Solutions

  1. Check i.ResultId.HasValue before converting; only convert result-producing instructions.
  2. Filter the instruction stream, e.g. Where(i => i.ResultId != null) before selecting.
  3. Verify the target instruction's opcode is one that defines a result (per the SPIR-V spec grammar).
  4. If the instruction genuinely should have a result id, inspect parsing — the word offset for the result id may be miscomputed.

Example fix

// before
IdRef id = instructions.First(i => i.OpCode == Op.OpTypeFloat);
// after
IdRef id = instructions.First(i => i.OpCode == Op.OpTypeFloat && i.ResultId != null);
Defensive patterns

Strategy: type-guard

Validate before calling

if (instruction.ResultId is null)
    throw new InvalidOperationException("Instruction produces no result id; cannot convert to IdRef");

Type guard

static bool HasResultId(this Instruction i) => i.ResultId.HasValue;

Try / catch

try { IdRef id = instruction; }
catch (Exception ex) when (ex.Message == "Instruction has no result id") { /* select a different instruction or skip */ }

Prevention

When it happens

Trigger: Implicitly casting an Instruction that produces no result to IdRef, e.g. IdRef r = module.Instructions.First(i => i.OpCode == Op.OpReturn); or passing such an instruction to a method accepting IdRef.

Common situations: Linq lookups over instruction streams returning the first matching opcode without filtering for result-producing ops (OpTypeInt, OpConstant, etc.); iterating instructions after SPIR-V parsing where result-less ops appear (most Op* control-flow/store instructions).

Related errors


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

Appendix: source

Thrown at sources/shaders/Stride.Shaders.Spirv/MemoryInstruction.cs:18

using System.Runtime.CompilerServices;
using Stride.Shaders.Spirv.Core.Buffers;
using Stride.Shaders.Spirv.Core.Parsing;
using static Stride.Shaders.Spirv.Specification;


namespace Stride.Shaders.Spirv.Core;

/// <summary>
/// Representation of an instruction from a memory slice.
/// </summary>
/// <param name="Buffer"></param>
/// <param name="Words"></param>
public record struct Instruction(Memory<int> Memory)
{
    public static Instruction Empty { get; } = new(Memory<int>.Empty);

    public static implicit operator IdRef(Instruction i) => new(i.ResultId ?? throw new Exception("Instruction has no result id"));
    public static implicit operator IdResultType(Instruction i) => new(i.ResultId ?? throw new Exception("Instruction has no result id"));


    public readonly Op OpCode => (Op)(Words[0] & 0xFFFF);
    public int? ResultId { get => GetResultId(); set => SetResultId(value); }
    public int? ResultType { get => GetResultType(); set => SetResultType(value); }
    public readonly int WordCount => Words.Length;
    public readonly Span<int> Operands => Memory[1..].Span;

    public readonly Span<int> Words => Memory.Span;

    public bool IsEmpty => Words.IsEmpty;

    public TWrapper UnsafeAs<TWrapper>()
        where TWrapper : struct, IWrapperInstruction, allows ref struct
    {
        return new TWrapper()
        {

View on GitHub (pinned to 96fad776d2)