{"record":{"id":"c537a9809dec768f","repo":"stride3d/stride","slug":"sdl-gamecontroller-already-opened-deviceindex-guid","errorCode":null,"errorMessage":"SDL GameController already opened {deviceIndex}/{*(Guid*)&joystickId}/{joystickName}","messagePattern":"SDL GameController already opened (.+?)/(.+?)/(.+?)","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"sources/engine/Stride.Input/SDL/InputSourceSDL.cs","lineNumber":102,"sourceCode":"        }\n\n        public override void Scan()\n        {\n            for (int i = 0; i < SDL.NumJoysticks(); i++)\n            { \n                if (!joystickInstanceIdToDeviceId.ContainsKey(GetJoystickInstanceId(i)))\n                {\n                    OpenDevice(i);\n                }\n            }\n        }\n\n        private void OpenDevice(int deviceIndex)\n        {\n            var joystickId = SDL.JoystickGetDeviceGUID(deviceIndex);\n            var joystickName = SDL.JoystickNameForIndexS(deviceIndex);\n            if (joystickInstanceIdToDeviceId.ContainsKey(GetJoystickInstanceId(deviceIndex)))\n                throw new InvalidOperationException($\"SDL GameController already opened {deviceIndex}/{*(Guid*)&joystickId}/{joystickName}\");\n\n            var controller = new GameControllerSDL(this, deviceIndex);\n\n            IInputDevice resultingDevice = controller;\n\n            // Find gamepad layout\n            var layout = GamePadLayouts.FindLayout(this, controller);\n            if (layout != null)\n            {\n                // Create a gamepad wrapping around the controller\n                var gamePad = new GamePadSDL(this, inputManager, controller, layout);\n                resultingDevice = gamePad; // Register gamepad instead\n            }\n\n            controller.Disconnected += (sender, args) =>\n            {\n                // Queue device for removal\n                devicesToRemove.Add(resultingDevice.Id);","sourceCodeStart":84,"sourceCodeEnd":120,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/engine/Stride.Input/SDL/InputSourceSDL.cs#L84-L120","documentation":"InputSourceSDL.OpenDevice tracks already-open joysticks by joystick instance id in joystickInstanceIdToDeviceId. If OpenDevice is called for a device whose instance id is already mapped, it throws InvalidOperationException with the device index, GUID and name. Opening the same SDL game controller twice would create duplicate device objects for one physical device.","triggerScenarios":"SDL raising a device-added event twice for the same instance id (e.g. Connect/Disconnect events coalesced or replayed), or calling OpenDevice manually for an index that was already opened.","commonSituations":"SDL joystick hot-plug storms on some platforms/drivers; re-scanning device lists without clearing state; driver quirks where unplug/replug reuses the same instance id before cleanup ran.","solutions":["Check joystickInstanceIdToDeviceId before calling OpenDevice and skip if the instance id is already present","Ensure device-removed handling runs so stale instance ids are cleaned before re-open","Debounce SDL controller added/removed events before opening","Log the device index/GUID from the message to identify the duplicated device and its source of double-open"],"exampleFix":"// before\nOpenDevice(deviceIndex); // may already be open\n// after\nif (!joystickInstanceIdToDeviceId.ContainsKey(GetJoystickInstanceId(deviceIndex)))\n    OpenDevice(deviceIndex);","handlingStrategy":"validation","validationCode":"if (!joystickInstanceIdToDeviceId.ContainsKey(GetJoystickInstanceId(deviceIndex)))\n    OpenDevice(deviceIndex);","typeGuard":null,"tryCatchPattern":"try { sourceOpenDevice(deviceIndex); } catch (InvalidOperationException) { /* already open, ignore */ }","preventionTips":["Process SDL joystick added events idempotently","Ensure removal handling clears instance-id mappings before the same id can be reopened","Debounce rapid connect/disconnect events from the OS"],"tags":["input","sdl","gamepad","duplicate-device"],"backgroundTag":"file-already-exists","analyzedSha":"96fad776d210c221682aac1ccdf4c79dc046fc38","analyzedAt":"2026-09-14T02:59:31.279Z","contentChangedAt":"2026-09-14T02:59:31.279Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}