stride3d/stride · error · InvalidOperationException

Not a valid gamepad

Error message

Not a valid gamepad

What it means

GetFreeGamePadIndex looks up a free index for a gamepad that must belong to the manager's GamePads collection. If the passed IGamePadDevice is not in GamePads, Stride throws InvalidOperationException because it cannot assign an index to a device it does not manage (null is rejected earlier with ArgumentNullException).

Solutions

  1. Pass a gamepad from inputManager.GamePads rather than constructing your own.
  2. Verify the gamepad is still connected: check GamePads.Contains(pad) before calling.
  3. Re-fetch the device reference after connection changes instead of caching it.

Example fix

// before
var idx = input.GetFreeGamePadIndex(new FakeGamePad());
// after
var pad = input.GamePads.FirstOrDefault();
var idx = pad != null ? input.GetFreeGamePadIndex(pad) : -1;
Defensive patterns

Strategy: type-guard

Validate before calling

bool IsValidPad(IGamePadDevice pad, InputManager input) => pad != null && input.GamePads.Contains(pad);

Type guard

IGamePadDevice GetManagedPad(InputManager input, IGamePadDevice pad) => input.GamePads.Contains(pad) ? pad : null;

Try / catch

try { var idx = input.GetFreeGamePadIndex(pad); }
catch (InvalidOperationException ex) when (ex.Message == "Not a valid gamepad") { idx = -1; }

Prevention

When it happens

Trigger: Calling inputManager.GetFreeGamePadIndex with a gamepad instance obtained outside the manager (mock, detached device, or another manager's device).

Common situations: Unit tests using fake gamepads; a gamepad removed from GamePads (unplugged) before the index request; passing a stale cached device reference.

Understand the failure class

Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.

Related errors


AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14). Data as JSON: /api/errors/60f2e9bdb82449d2. Report an issue: GitHub.

Appendix: source

Thrown at sources/engine/Stride.Input/InputManager.cs:652

        /// Resets the <see cref="Sources"/> collection back to it's default values
        /// </summary>
        public void ResetSources()
        {
            Sources.Clear();
            AddSources();
        }
        
        /// <summary>
        /// Suggests an index that is unused for a given <see cref="IGamePadDevice"/>
        /// </summary>
        /// <param name="gamePad">The gamepad to find an index for</param>
        /// <returns>The unused gamepad index</returns>
        public int GetFreeGamePadIndex(IGamePadDevice gamePad)
        {
            if (gamePad == null)
                throw new ArgumentNullException(nameof(gamePad));
            if (!GamePads.Contains(gamePad))
                throw new InvalidOperationException("Not a valid gamepad");

            // Find a new index for this game controller
            int targetIndex = 0;
            for (int i = 0; i < gamePadRequestedIndex.Count; i++)
            {
                var collection = gamePadRequestedIndex[i];
                if (collection.Count == 0 || (collection.Count == 1 && collection[0] == gamePad))
                {
                    targetIndex = i;
                    break;
                }
                targetIndex++;
            }

            return targetIndex;
        }

        private void AddSources()

View on GitHub (pinned to 96fad776d2)