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
- Check i.ResultId.HasValue before converting; only convert result-producing instructions.
- Filter the instruction stream, e.g. Where(i => i.ResultId != null) before selecting.
- Verify the target instruction's opcode is one that defines a result (per the SPIR-V spec grammar).
- 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
- Filter instruction streams with Where(i => i.ResultId != null) before converting to IdRef.
- Know which opcodes define results (types, constants, variables) vs. which don't (branches, stores, returns).
- Prefer explicit i.ResultId.Value access over implicit conversion so failures are local and clear.
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
- 64bit integers
- Binary operator not supported for element type
- BuildInheritanceListWithoutSelf: OpMixinInheritSDSL…
- Can't add type
- Can't cast between array of different sizes
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)