{"record":{"id":"0518cb2005803030","repo":"stride3d/stride","slug":"input-device-was-not-registered","errorCode":null,"errorMessage":"Input device was not registered","messagePattern":"Input device was not registered","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"sources/engine/Stride.Input/InputManager.cs","lineNumber":829,"sourceCode":"            }\n            else if (device is IGamePadDevice)\n            {\n                RegisterGamePad((IGamePadDevice)device);\n                gamePads.Sort((l, r) => -l.Priority.CompareTo(r.Priority));\n            }\n            else if (device is ISensorDevice)\n            {\n                RegisterSensor((ISensorDevice)device);\n            }\n            UpdateConnectedDevices();\n\n            DeviceAdded?.Invoke(this, new DeviceChangedEventArgs { Device = device, Source = source, Type = DeviceChangedEventType.Added });\n        }\n\n        private void OnInputDeviceRemoved(IInputDevice device)\n        {\n            if (!devices.Contains(device))\n                throw new InvalidOperationException(\"Input device was not registered\");\n\n            var source = device.Source;\n            devices.Remove(device);\n            devicesById.Remove(device.Id);\n\n            if (device is IKeyboardDevice)\n            {\n                UnregisterKeyboard((IKeyboardDevice)device);\n            }\n            else if (device is IPointerDevice)\n            {\n                UnregisterPointer((IPointerDevice)device);\n            }\n            else if (device is IGameControllerDevice)\n            {\n                UnregisterGameController((IGameControllerDevice)device);\n            }\n            else if (device is IGamePadDevice)","sourceCodeStart":811,"sourceCodeEnd":847,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/engine/Stride.Input/InputManager.cs#L811-L847","documentation":"OnInputDeviceRemoved validates that the device being removed is currently registered; if devices.Contains(device) is false, Stride throws InvalidOperationException, preventing double-removal or removal of foreign devices from internal collections.","triggerScenarios":"A source raising a Remove notification for a device that was never added, or raising Remove twice for the same device; a device from one source being removed via another source's collection.","commonSituations":"Custom input sources with buggy device lifecycle (double Remove on shutdown); device removal racing with its own earlier removal; sources disposing without having added devices.","solutions":["Only raise CollectionChanged Remove for devices previously announced with Add.","Guard custom source teardown so each device removal fires once.","Verify device lifetime management in the custom IInputSource implementation."],"exampleFix":"// before\nDevices.Remove(device); Devices.Remove(device); // second raise throws\n// after\nif (Devices.Contains(device)) Devices.Remove(device);","handlingStrategy":"type-guard","validationCode":"bool CanRemove(IInputDevice d) => d != null && devices.Contains(d);","typeGuard":"bool IsRegistered(InputManager input, IInputDevice d) => input.Sources.SelectMany(s => s.Devices).Any(x => ReferenceEquals(x, d));","tryCatchPattern":"try { /* source teardown */ }\ncatch (InvalidOperationException ex) when (ex.Message == \"Input device was not registered\") { /* already removed: ignore */ }","preventionTips":["Raise Remove only for devices previously announced via Add.","Make custom source teardown idempotent (remove each device once).","Serialize connect/disconnect handling to avoid double teardown."],"tags":["input","device-lifecycle","invalid-state"],"backgroundTag":"entity-not-found","analyzedSha":"96fad776d210c221682aac1ccdf4c79dc046fc38","analyzedAt":"2026-09-14T02:59:31.279Z","contentChangedAt":"2026-09-14T02:59:31.279Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}