{"record":{"id":"0dc802331cc66427","repo":"stride3d/stride","slug":"xinput-device-already-opened-index","errorCode":null,"errorMessage":"XInput device already opened {index}","messagePattern":"XInput device already opened (.+?)","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"sources/engine/Stride.Input/Windows/InputSourceWindowsXInput.cs","lineNumber":110,"sourceCode":"                    if (controllers[i].IsConnected)\n                    {\n                        OpenDevice(i);\n                    }\n                }\n            }\n        }\n\n        /// <summary>\n        /// Opens a new gamepad\n        /// </summary>\n        /// <param name=\"instance\">The gamepad</param>\n        public void OpenDevice(int index)\n        {\n            if (index < 0 || index >= XInputGamePadCount)\n                throw new IndexOutOfRangeException($\"Invalid XInput device index {index}\");\n\n            if (devices[index] != null)\n                throw new InvalidOperationException($\"XInput device already opened {index}\");\n\n            var newGamepad = new GamePadXInput(this, controllers[index], controllerIds[index], index);\n            newGamepad.Disconnected += (sender, args) =>\n            {\n                // Queue device for removal\n                devicesToRemove.Add(index);\n            };\n\n            devices[index] = newGamepad;\n            RegisterDevice(newGamepad);\n        }\n    }\n}\n\n#endif","sourceCodeStart":92,"sourceCodeEnd":125,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/engine/Stride.Input/Windows/InputSourceWindowsXInput.cs#L92-L125","documentation":"InputSourceWindowsXInput.OpenDevice throws InvalidOperationException when devices[index] is already occupied, i.e. the gamepad at that XInput slot was already opened. Only one GamePadXInput may own a controller slot; opening a second would produce duplicate event streams.","triggerScenarios":"Calling OpenDevice(index) twice for the same slot without closing the first, or Scan running again while the device is still registered (devicesToRemove not yet processed).","commonSituations":"Rapid unplug/replug before the pending removal is flushed; manual double-open in custom gamepad management; concurrent Scan invocations.","solutions":["Check devices[index] != null before calling OpenDevice.","Wait for/trigger the pending devicesToRemove cleanup before reopening the slot.","Close or dispose the existing GamePadXInput before opening a new one on the same index."],"exampleFix":"// before\ninputSource.OpenDevice(0);\ninputSource.OpenDevice(0); // crash\n// after\nif (inputSource.Devices[0] == null)\n    inputSource.OpenDevice(0);","handlingStrategy":"validation","validationCode":"if (inputSource.Devices[index] == null)\n    inputSource.OpenDevice(index);","typeGuard":"bool SlotIsFree(int i) => inputSource.Devices[i] == null;","tryCatchPattern":"try\n{\n    inputSource.OpenDevice(index);\n}\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"already opened\"))\n{\n    // Slot already in use; reuse the existing gamepad instead.\n}","preventionTips":["Check the slot before opening; reuse the existing GamePadXInput instance.","Flush pending devicesToRemove before rescanning.","Route all open/close operations through one owner to avoid duplicate opens."],"tags":["xinput","duplicate-device","gamepad","windows"],"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"}