stride3d/stride · error · InvalidOperationException

Could not find a store operation right after Interop.Pin

Error message

Could not find a store operation right after Interop.Pin

What it means

ReplacePinStructGeneric expects an Interop.Pin to be followed by a store instruction (stloc) that captures the pinned result; when the next instruction is not a recognized store, it throws this InvalidOperationException since the pinned-variable transform cannot proceed.

Solutions

  1. Assign the Interop.Pin result to a local variable so a stloc follows the call
  2. Rewrite single-expression usage into explicit statement form (var h = Interop.Pin(...))
  3. Match the pattern used by Stride's own samples for pinning generic structs
  4. Update Stride if your compiler emits a pattern the processor doesn't recognize

Example fix

// before
_ = Interop.Pin(myStruct, out handle); // result not stored to tracked local
// after
var pinned = Interop.Pin(myStruct, out handle); // followed by stloc
Defensive patterns

Strategy: validation

Validate before calling

// ensure the pin result is assigned: `var pinned = Interop.Pin(x, out h);` guarantees a stloc follows

Try / catch

catch (InvalidOperationException ex) when (ex.Message.Contains("store operation right after Interop.Pin"))
{
    // assign the pin result to a local variable and retry the build
}

Prevention

When it happens

Trigger: PatchMethod processing Interop.Pin on a generic struct where the IL after the pin call does not store the result into a local (result discarded, used inline, or compiler reordered the code).

Common situations: Discarding the return of Interop.Pin instead of assigning it; expression-level usage where the result is consumed on the stack directly; debug vs release IL differences altering store placement.

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/7449f3aa2e98fd94. Report an issue: GitHub.

Appendix: source

Thrown at sources/core/Stride.Core.AssemblyProcessor/InteropProcessor.cs:280

        else if (nextStoreInstruction.OpCode == OpCodes.Stloc_2)
        {
            variableIndex = 2;
        }
        else if (nextStoreInstruction.OpCode == OpCodes.Stloc_3)
        {
            variableIndex = 3;
        }
        else if (nextStoreInstruction.OpCode == OpCodes.Stloc_S)
        {
            variableIndex = ((VariableReference)nextStoreInstruction.Operand).Index;
        }
        else if (nextStoreInstruction.OpCode == OpCodes.Stloc)
        {
            variableIndex = ((VariableReference)nextStoreInstruction.Operand).Index;
        }
        else
        {
            throw new InvalidOperationException("Could not find a store operation right after Interop.Pin");
        }

        // Transform variable from:
        //   valuetype Struct s
        // to:
        //   valuetype Struct& modopt([mscorlib]System.Runtime.CompilerServices.IsExplicitlyDereferenced) pinned s,
        var variable = method.Body.Variables[variableIndex];
        variable.VariableType = variable.VariableType
            .MakeByReferenceType()
            //.MakeOptionalModifierType(typeof(IsExplicitlyDereferenced))
            .MakePinnedType();

        // Remove call to Interop.Pin:
        ilProcessor.Remove(pinToPatch);

        // Transform all ldloca with this variable into ldloc:
        for (int index = 0; index < ilProcessor.Body.Instructions.Count; index++)
        {

View on GitHub (pinned to 96fad776d2)