{"record":{"id":"4d78a6a6f92749b1","repo":"stride3d/stride","slug":"input-device-with-id-device-id-was-not-registered","errorCode":null,"errorMessage":"Input device with Id {device.Id} was not registered","messagePattern":"Input device with Id (.+?) was not registered","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"sources/engine/Stride.Input/InputSourceBase.cs","lineNumber":62,"sourceCode":"        /// Adds the device to the list <see cref=\"Devices\"/>\n        /// </summary>\n        /// <param name=\"device\">The device</param>\n        protected void RegisterDevice(IInputDevice device)\n        {\n            if (Devices.ContainsKey(device.Id))\n                throw new InvalidOperationException($\"Input device with Id {device.Id} already registered\");\n\n            Devices.Add(device.Id, device);\n        }\n\n        /// <summary>\n        /// CRemoves the device from the list <see cref=\"Devices\"/>\n        /// </summary>\n        /// <param name=\"device\">The device</param>\n        protected void UnregisterDevice(IInputDevice device)\n        {\n            if (!Devices.Remove(device.Id))\n                throw new InvalidOperationException($\"Input device with Id {device.Id} was not registered\");\n        }\n    }\n}\n","sourceCodeStart":44,"sourceCodeEnd":66,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/engine/Stride.Input/InputSourceBase.cs#L44-L66","documentation":"InputSourceBase.UnregisterDevice throws when Devices.Remove(device.Id) returns false, i.e. the device being removed was never registered (or was already removed). The input source calls this from Update during device lifecycle changes, so it indicates bookkeeping drift between the concrete source's own collections and the base Devices dictionary.","triggerScenarios":"Calling UnregisterDevice with a device that was never registered via RegisterDevice, or calling it twice for the same device; also triggered internally from Update when a Disconnected event or source logic removes a device whose Id is absent from Devices.","commonSituations":"Double-dispose of a game controller (Dispose fires Disconnected, source tries to unregister twice); custom simulated-device removal code that forgets to Add first; race between Update's cleanup pass and manual removal in user code.","solutions":["Only call UnregisterDevice for devices previously registered through RegisterDevice","Guard removal with Devices.ContainsKey(device.Id) before unregistering","Fix double-dispose paths so Disconnected/Remove logic runs only once (idempotent flags)","Keep the subclass's own collection (gamePads, mice, ...) in sync: unregister before removing from it"],"exampleFix":"// before\nif (Devices.ContainsKey(device.Id))\n    UnregisterDevice(device);\nUnregisterDevice(device); // throws if already removed\n// after\nif (Devices.ContainsKey(device.Id))\n    UnregisterDevice(device);","handlingStrategy":"validation","validationCode":"if (inputSource.Devices.ContainsKey(device.Id)) inputSource.UnregisterDevice(device);","typeGuard":null,"tryCatchPattern":"try { source.UnregisterDevice(device); } catch (InvalidOperationException) { /* already unregistered */ }","preventionTips":["Track which devices you registered so you never unregister unknown ones","Make removal idempotent with a disposed/removed flag on your device wrapper","Unregister before removing the device from your own collections"],"tags":["input","csharp","device-registration","state-inconsistency"],"backgroundTag":"resource-not-found","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"}