{"record":{"id":"d24dfe522cca0811","repo":"stride3d/stride","slug":"failed-to-unregister-a-mouse-device-for-raw-input","errorCode":null,"errorMessage":"Failed to unregister a mouse device for raw input","messagePattern":"Failed to unregister a mouse device for raw input","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"sources/engine/Stride.Input/Windows/RawInput/RawInputMouse.cs","lineNumber":46,"sourceCode":"        public void Start()\n        {\n            var result = RawInput.RegisterDevice(UsagePage.HID_USAGE_PAGE_GENERIC, UsageId.HID_USAGE_GENERIC_MOUSE, ModeFlags.RIDEV_INPUTSINK, targetWindow);\n            if (!result)\n            {\n                throw new Exception(\"Failed to register a mouse device for raw input\");\n            }\n\n            Application.AddMessageFilter(messageFilter);\n        }\n\n        public void End()\n        {\n            Application.RemoveMessageFilter(messageFilter);\n\n            var result = RawInput.RegisterDevice(UsagePage.HID_USAGE_PAGE_GENERIC, UsageId.HID_USAGE_GENERIC_MOUSE, ModeFlags.RIDEV_REMOVE, IntPtr.Zero);\n            if (!result)\n            {\n                throw new Exception(\"Failed to unregister a mouse device for raw input\");\n            }\n        }\n\n        public void HandleInputMessage(RawInput.RawMouse mouseInput)\n        {\n            // TODO: Handle absolute pointer positions. These events can happen with drawing tablets or RDP for example\n            events?.Invoke(null, new RawInputMouseEventArgs\n            {\n                isRelative = (mouseInput.Flags & MOUSE_MOVE_ABSOLUTE_BIT) == 0,\n                X = mouseInput.LastX,\n                Y = mouseInput.LastY\n            });\n        }\n\n        protected virtual void Dispose(bool disposing)\n        {\n            if (!disposedValue)\n            {","sourceCodeStart":28,"sourceCodeEnd":64,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/engine/Stride.Input/Windows/RawInput/RawInputMouse.cs#L28-L64","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Ensure End() is called at most once and only after a successful Start().","Dispose input before destroying the target window during shutdown.","Make the remove flags/hwnd parameters match the original registration; retry on a valid message window if needed.","Wrap Dispose so a failure here is logged rather than masking the original shutdown exception."],"exampleFix":"// before\npublic void Dispose() { End(); End(); } // second End throws\n// after\nprivate bool ended;\npublic void Dispose() { if (ended) return; ended = true; End(); }","handlingStrategy":"try-catch","validationCode":"if (started) End(); // only unregister after a successful Start","typeGuard":"bool CanEnd(RawInputMouse m) => m != null && m.Started && !m.Disposed;","tryCatchPattern":"try { mouse.End(); } catch (Exception ex) when (ex.Message.Contains(\"Failed to unregister a mouse device\")) { Log.Warn(ex); /* continue teardown */ }","preventionTips":["Make Start/End symmetric and call End at most once (guard with a bool)","Dispose input components before disposing the window during shutdown","Swallow-and-log teardown failures so they don't mask original errors","Never call End after a failed Start without re-checking state"],"tags":["raw-input","windows","input-device-unregistration","teardown"],"backgroundTag":"invalid-state-transition","analyzedSha":"96fad776d210c221682aac1ccdf4c79dc046fc38","analyzedAt":"2026-09-14T02:59:31.279Z","contentChangedAt":"2026-09-14T02:59:31.279Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}