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
- Pass a gamepad from inputManager.GamePads rather than constructing your own.
- Verify the gamepad is still connected: check GamePads.Contains(pad) before calling.
- 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
- Only pass devices obtained from inputManager.GamePads.
- Re-check GamePads.Contains after connection changes.
- Use null checks plus Contains before calling.
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
- This GamePad's index can not be changed
- Gamepad index was out of range
- Something should handle controller disconnect
- SDL GameController already opened
- Can not set more than one button at a time
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)