stride3d/stride · error · InvalidOperationException

Input device with Id

Error message

Input device with Id {device.Id} already registered

What it means

InputSourceBase.RegisterDevice guards its Devices dictionary against duplicate keys. When a device implementation (or the owning InputSource) tries to register an IInputDevice whose Id is already present, the base class refuses rather than silently overwrite the existing device, throwing InvalidOperationException. This is an internal state invariant: each registered device must have a unique Id.

Solutions

  1. Ensure UnregisterDevice is called before re-registering a device with the same Id
  2. Give each device a unique Id (use instance handles/GUIDs, not names or indices)
  3. Check Devices.ContainsKey(device.Id) before calling RegisterDevice and skip or remove the stale entry first
  4. If re-creating a device on reconnect, dispose/unregister the old instance before constructing the new one

Example fix

// before
source.RegisterDevice(newGamePad); // old pad with same Id still registered
// after
var old = source.Devices.Values.OfType<GamePadSimulated>().FirstOrDefault(d => d.Id == newGamePad.Id);
if (old != null) source.RemoveGamePad(old);
source.RegisterDevice(newGamePad);
Defensive patterns

Strategy: validation

Validate before calling

if (inputSource.Devices.ContainsKey(device.Id)) inputSource.UnregisterDevice(device); // or skip
inputSource.RegisterDevice(device);

Type guard

bool IsRegistered(InputSourceBase source, IInputDevice d) => source.Devices.ContainsKey(d.Id);

Prevention

When it happens

Trigger: Calling RegisterDevice twice with the same device instance, or with two distinct device objects that report the same Id (e.g. a device re-created after reconnect without unregistering the old one, or a subclass assigning a constant Id to multiple instances).

Common situations: Hot-plug handling that re-adds a controller on reconnect while the old entry is still registered; custom input sources that generate device IDs from index/name rather than a unique handle; game/editor reinitialization of the input system without disposing the previous source.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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

Appendix: source

Thrown at sources/engine/Stride.Input/InputSourceBase.cs:50

        }

        /// <summary>
        /// Unregisters all devices registered with <see cref="RegisterDevice"/> which have not been unregistered yet
        /// </summary>
        public virtual void Dispose()
        {
            // Remove all devices, done by clearing the tracking dictionary
            Devices.Clear();
        }

        /// <summary>
        /// Adds the device to the list <see cref="Devices"/>
        /// </summary>
        /// <param name="device">The device</param>
        protected void RegisterDevice(IInputDevice device)
        {
            if (Devices.ContainsKey(device.Id))
                throw new InvalidOperationException($"Input device with Id {device.Id} already registered");

            Devices.Add(device.Id, device);
        }

        /// <summary>
        /// CRemoves the device from the list <see cref="Devices"/>
        /// </summary>
        /// <param name="device">The device</param>
        protected void UnregisterDevice(IInputDevice device)
        {
            if (!Devices.Remove(device.Id))
                throw new InvalidOperationException($"Input device with Id {device.Id} was not registered");
        }
    }
}

View on GitHub (pinned to 96fad776d2)