stride3d/stride · error · Exception

Failed to unregister a mouse device for raw input

Error message

Failed to unregister a mouse device for raw input

What it means

RawInputMouse.End unregisters the mouse device by calling RawInput.RegisterDevice with RIDEV_REMOVE and a null target window. If that Win32 call fails, the library throws this exception while tearing down input, typically from Dispose.

Solutions

  1. Ensure End() is called at most once and only after a successful Start().
  2. Dispose input before destroying the target window during shutdown.
  3. Make the remove flags/hwnd parameters match the original registration; retry on a valid message window if needed.
  4. Wrap Dispose so a failure here is logged rather than masking the original shutdown exception.

Example fix

// before
public void Dispose() { End(); End(); } // second End throws
// after
private bool ended;
public void Dispose() { if (ended) return; ended = true; End(); }
Defensive patterns

Strategy: try-catch

Validate before calling

if (started) End(); // only unregister after a successful Start

Type guard

bool CanEnd(RawInputMouse m) => m != null && m.Started && !m.Disposed;

Try / catch

try { mouse.End(); } catch (Exception ex) when (ex.Message.Contains("Failed to unregister a mouse device")) { Log.Warn(ex); /* continue teardown */ }

Prevention

When it happens

Trigger: Calling End()/Dispose() when the mouse device is not currently registered (Start never succeeded or End called twice), or when the RIDEV_REMOVE registration is rejected because the remove parameters do not match an existing registration.

Common situations: Double-dispose of the RawInputMouse; disposing after a failed Start; window handle already destroyed so the remove request cannot be matched; application shutdown ordering removes the window before input disposal.

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


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

Appendix: source

Thrown at sources/engine/Stride.Input/Windows/RawInput/RawInputMouse.cs:46

        public void Start()
        {
            var result = RawInput.RegisterDevice(UsagePage.HID_USAGE_PAGE_GENERIC, UsageId.HID_USAGE_GENERIC_MOUSE, ModeFlags.RIDEV_INPUTSINK, targetWindow);
            if (!result)
            {
                throw new Exception("Failed to register a mouse device for raw input");
            }

            Application.AddMessageFilter(messageFilter);
        }

        public void End()
        {
            Application.RemoveMessageFilter(messageFilter);

            var result = RawInput.RegisterDevice(UsagePage.HID_USAGE_PAGE_GENERIC, UsageId.HID_USAGE_GENERIC_MOUSE, ModeFlags.RIDEV_REMOVE, IntPtr.Zero);
            if (!result)
            {
                throw new Exception("Failed to unregister a mouse device for raw input");
            }
        }

        public void HandleInputMessage(RawInput.RawMouse mouseInput)
        {
            // TODO: Handle absolute pointer positions. These events can happen with drawing tablets or RDP for example
            events?.Invoke(null, new RawInputMouseEventArgs
            {
                isRelative = (mouseInput.Flags & MOUSE_MOVE_ABSOLUTE_BIT) == 0,
                X = mouseInput.LastX,
                Y = mouseInput.LastY
            });
        }

        protected virtual void Dispose(bool disposing)
        {
            if (!disposedValue)
            {

View on GitHub (pinned to 96fad776d2)