stride3d/stride · error · InvalidOperationException
Passthrough already started
Error message
Passthrough already started
What it means
StartPassthrough() throws this InvalidOperationException when the FB passthrough extension instance reports it is already Enabled. Each device can have only one active passthrough session; starting a second one would conflict with the first. Callers should keep the IDisposable returned by StartPassthrough and dispose it to stop passthrough before starting again.
Solutions
- Keep the IDisposable from StartPassthrough and dispose it before calling StartPassthrough again.
- Track a bool/nullable field so StartPassthrough is only invoked when no passthrough session is active.
- Wrap StartPassthrough in a check (or a try/catch for InvalidOperationException) to make starting idempotent.
Example fix
// before passthrough = hmd.StartPassthrough(); // called every frame, throws once enabled // after passthrough ??= hmd.StartPassthrough(); // start once, dispose to stop // or: if (passthrough == null) passthrough = hmd.StartPassthrough();
Defensive patterns
Strategy: type-guard
Validate before calling
if (activePassthrough != null) return; // already started currentPassthrough = hmd.StartPassthrough();
Type guard
bool PassthroughActive(IDisposable? session) => session != null;
Try / catch
try { passthrough = hmd.StartPassthrough(); }
catch (InvalidOperationException) { /* already started; reuse existing session */ } Prevention
- Store the IDisposable returned by StartPassthrough and dispose before restarting.
- Use null-coalescing/once-only initialization for the passthrough session.
- Stop passthrough deterministically on scene exit.
When it happens
Trigger: Calling StartPassthrough() twice without disposing the IDisposable returned by the first call; storing the first disposable but calling StartPassthrough again on a later frame.
Common situations: Double initialization from both a scene script and a game-loop update; re-entering a VR scene that starts passthrough each time without stopping the previous session; missing ownership tracking of the returned disposable.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- The passthrough mode needs to be enabled at device creation
- The device does not support passthrough mode
- Don't know button:
- OpenXR error! Current implementation doesn't support…
- OpenXR is only compatible with DirectX11
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/157a21834f8bf2bf.
Report an issue: GitHub.
Appendix: source
Thrown at sources/engine/Stride.VirtualReality/OpenXR/OpenXRHmd.cs:395
Type = StructureType.InteractionProfileState,
Next = null
};
Xr.StringToPath(Instance, "/user/hand/left", ref leftHandPath);
}
public override IDisposable StartPassthrough()
{
if (!passthroughRequested)
throw new InvalidOperationException("The passthrough mode needs to be enabled at device creation");
if (!SupportsPassthrough)
throw new NotSupportedException("The device does not support passthrough mode");
if (passthroughExt is null)
passthroughExt = new OpenXRExt_FB_Passthrough(Xr, globalSession, Instance);
if (passthroughExt.Enabled)
throw new InvalidOperationException("Passthrough already started");
passthroughExt.Enabled = true;
return new AnonymousDisposable(() => passthroughExt.Enabled = false);
}
private void EndNullFrame()
{
FrameEndInfo frame_end_info = new FrameEndInfo()
{
Type = StructureType.FrameEndInfo,
DisplayTime = globalFrameState.PredictedDisplayTime,
EnvironmentBlendMode = EnvironmentBlendMode.Opaque,
LayerCount = 0,
Layers = null,
Next = null
};
Xr.EndFrame(globalSession, frame_end_info).CheckResult();View on GitHub (pinned to 96fad776d2)