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
- Assign the Interop.Pin result to a local variable so a stloc follows the call
- Rewrite single-expression usage into explicit statement form (var h = Interop.Pin(...))
- Match the pattern used by Stride's own samples for pinning generic structs
- 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
- Never discard the Interop.Pin return value
- Write explicit statements rather than inline expressions when pinning
- Compare against Stride sample IL patterns for generic struct pinning
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
- Could not find a load operation right before Interop.Pin
- Could not resolve generic arguments
- Unsupported generic resolution.
- Missing mscorlib.dll from assembly
- FixedBuffer attribute is not supported.
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)