Skip to content

Conversation

@ekcoh
Copy link
Collaborator

@ekcoh ekcoh commented Nov 27, 2025

Description

This PR is a fix for a bug reported in ISXB-1767 (internal ticket). The reported problem is an IndexOutOfRangeException being thrown from InputManagerStateMonitors.AddStateChangeMonitor which leaves the Input System in an incomplete and inconsistent state preventing automatic recovery.

Recreating the exact scenario reported in the ticket was difficult since the reproduction case was a very large project, but I believe I have finally been able to recreate the exact scenario now in test case Actions_CanHandleDeviceDisconnectWithControlSchemesAndReconnect which is also added to this PR to prevent future regression. The scenario involves at least 2 devices being present and being associated with separate control schemes while triggering an action and disconnecting the associated device while disabling and reenabling an action map from the action cancellation callback.

The fix involves not allowing adding state monitors to a device with an invalid device index which prevents the problematic exception. In addition to throwing, the exception also has side-effects and leaves the system in an inconsistent state which leads to additional exceptions being thrown afterwards and prevents input bindings from going back into a resolved state. What is interesting is that the presence of control schemes is what creates this issue and it is not completely clear to me why this is essential.

Testing status & QA

Added a more or less exact reproduction of the problematic scenario in InputManagerStateMonitors.AddStateChangeMonitor. I would also recommend verifying the final version of this PR with the repro project to make sure it's properly solved.

Found another issue while testing this bug that I filed separately into ISXB-1776.

Overall Product Risks

  • Complexity: Medium - Central logic for detecting input and enabling actions modified
  • Halo Effect: Medium - Might have implication on any use of actions

Comments to reviewers

Recommend looking for other aspects or side-effects I might have overlooked. Additional insights of the control scheme aspect with relation to this bug is valuable.

To manually trigger the problem do the following reproduction steps:

  1. Setup an .inputactions asset with bindings for multiple devices, e.g. keyboard and gamepad including associated control schemes. Simplest is just setting Project-wide Input Actions up with the default created asset since it already contain these ingredients.
  2. Create a script that disables and enables an action map associated with the actions being tested, e.g. "Player" map, from within the cancellation callback for an action, e.g. "Jump" action. See example below:
using UnityEngine;
using UnityEngine.InputSystem;

public class Trigger : MonoBehaviour
{
    // Assumes "Jump" binding is used to trigger the problematic behavior.
    void Start()
    {
        var map = InputSystem.actions.FindActionMap("Player");
        var jump = map.FindAction("Jump");
        jump.performed += (ctx) => Debug.Log("Jump Performed");
        jump.canceled += ctx =>
        {
            map.Disable();
            map.Enable(); // <-- Triggers exception
        };
    }
}

If using ProjectWideInputActionsSampleScene the above script can just be attached to the "Cube" object or any other object.
3. Connect a gamepad, e.g. DualSense via USB cable (important since step 6 will be difficult otherwise).
4. Enter play-mode.
5. Press Jump button (E.g. "X" on a DualSense) and keep it pressed to ensure that the action is still in performed state.
6. With your free hand, disconnect the USB cable from the device while still holding "X".
7. Observe failed assert and exceptions in console. It seems the Input System cannot recover from this even if device is reconnected. With this PR the system shall both handle the error and auto-resolve bindings when device is reconnected.

Checklist

Before review:

  • Changelog entry added.
    • Explains the change in Changed, Fixed, Added sections.
    • For API change contains an example snippet and/or migration example.
    • JIRA ticket linked, example (case %%). If it is a private issue, just add the case ID without a link.
    • Jira port for the next release set as "Resolved".
  • Tests added/changed, if applicable.
    • Functional tests Area_CanDoX, Area_CanDoX_EvenIfYIsTheCase, Area_WhenIDoX_AndYHappens_ThisIsTheResult.
    • Performance tests.
    • Integration tests.
  • Docs for new/changed API's.
    • Xmldoc cross references are set correctly.
    • Added explanation how the API works.
    • Usage code examples added.
    • The manual is updated, if needed.

During merge:

  • Commit message for squash-merge is prefixed with one of the list:
    • NEW: ___.
    • FIX: ___.
    • DOCS: ___.
    • CHANGE: ___.
    • RELEASE: 1.1.0-preview.3.

@ekcoh ekcoh changed the title FIX: IndexOutOfBoundException when enabling InputActionMap. FIX: IndexOutOfRangeException when enabling InputActionMap. Nov 27, 2025
@ekcoh ekcoh added the work in progress Indicates that the PR is work in progress and any review efforts can be post-poned. label Nov 27, 2025
@ekcoh ekcoh changed the title FIX: IndexOutOfRangeException when enabling InputActionMap. FIX: IndexOutOfRangeException when enabling InputActionMap. (ISXB-1767) Nov 28, 2025
…at disabling controls doesn't require the same check.
@ekcoh ekcoh removed the work in progress Indicates that the PR is work in progress and any review efforts can be post-poned. label Nov 28, 2025
@ekcoh ekcoh marked this pull request as ready for review November 28, 2025 08:04
@ekcoh ekcoh requested review from Pauliusd01, jfreire-unity and ritamerkl and removed request for ritamerkl November 28, 2025 08:04
@u-pr-agent
Copy link
Contributor

u-pr-agent bot commented Nov 28, 2025

PR Reviewer Guide 🔍

(Review updated until commit 3ebbcd6)

Here are some key observations to aid the review process:

⏱️ Estimated effort to review: 2 🔵🔵⚪⚪⚪

The PR involves a targeted fix for a specific exception and includes a regression test; the logic is straightforward and the scope is limited.
🏅 Score: 95

The fix correctly addresses the `IndexOutOfRangeException` by verifying device connectivity before enabling controls, and the added regression test accurately reproduces the reported scenario.
🧪 PR contains tests
🔒 No security concerns identified
⚡ No major issues detected
  • Update review

🤖 Helpful? Please react with 👍/👎 | Questions❓Please reach out in Slack #ask-u-pr-agent

@u-pr-agent
Copy link
Contributor

u-pr-agent bot commented Nov 28, 2025

PR Code Suggestions ✨

No code suggestions found for the PR.

@codecov-github-com
Copy link

codecov-github-com bot commented Nov 28, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

@@             Coverage Diff             @@
##           develop    #2296      +/-   ##
===========================================
+ Coverage    77.95%   77.97%   +0.01%     
===========================================
  Files          477      477              
  Lines        97416    97452      +36     
===========================================
+ Hits         75943    75985      +42     
+ Misses       21473    21467       -6     
Flag Coverage Δ
inputsystem_MacOS_2022.3 5.54% <0.00%> (-0.01%) ⬇️
inputsystem_MacOS_2022.3_project 75.50% <100.00%> (+0.01%) ⬆️
inputsystem_MacOS_6000.0 5.32% <0.00%> (-0.01%) ⬇️
inputsystem_MacOS_6000.0_project 77.42% <100.00%> (+0.01%) ⬆️
inputsystem_MacOS_6000.2 5.32% <0.00%> (-0.01%) ⬇️
inputsystem_MacOS_6000.2_project 77.41% <100.00%> (+<0.01%) ⬆️
inputsystem_MacOS_6000.3 5.32% <0.00%> (-0.01%) ⬇️
inputsystem_MacOS_6000.3_project 77.42% <100.00%> (+<0.01%) ⬆️
inputsystem_MacOS_6000.4 5.33% <0.00%> (-0.01%) ⬇️
inputsystem_MacOS_6000.4_project 77.44% <100.00%> (+0.01%) ⬆️
inputsystem_MacOS_6000.5 5.33% <0.00%> (-0.01%) ⬇️
inputsystem_MacOS_6000.5_project 77.42% <100.00%> (+0.01%) ⬆️
inputsystem_Ubuntu_2022.3 5.54% <0.00%> (-0.01%) ⬇️
inputsystem_Ubuntu_2022.3_project 75.30% <100.00%> (+0.01%) ⬆️
inputsystem_Ubuntu_6000.0 5.32% <0.00%> (-0.01%) ⬇️
inputsystem_Ubuntu_6000.0_project 77.22% <100.00%> (+<0.01%) ⬆️
inputsystem_Ubuntu_6000.2 5.32% <0.00%> (-0.01%) ⬇️
inputsystem_Ubuntu_6000.2_project 77.22% <100.00%> (+0.01%) ⬆️
inputsystem_Ubuntu_6000.3 5.32% <0.00%> (-0.01%) ⬇️
inputsystem_Ubuntu_6000.3_project 77.22% <100.00%> (+<0.01%) ⬆️
inputsystem_Ubuntu_6000.4 5.33% <0.00%> (-0.01%) ⬇️
inputsystem_Ubuntu_6000.4_project 77.23% <100.00%> (+<0.01%) ⬆️
inputsystem_Ubuntu_6000.5 5.33% <0.00%> (-0.01%) ⬇️
inputsystem_Ubuntu_6000.5_project 77.23% <100.00%> (+<0.01%) ⬆️
inputsystem_Windows_2022.3 5.54% <0.00%> (-0.01%) ⬇️
inputsystem_Windows_2022.3_project 75.63% <100.00%> (+0.01%) ⬆️
inputsystem_Windows_6000.0 5.32% <0.00%> (-0.01%) ⬇️
inputsystem_Windows_6000.0_project 77.55% <100.00%> (+0.01%) ⬆️
inputsystem_Windows_6000.2 5.32% <0.00%> (-0.01%) ⬇️
inputsystem_Windows_6000.2_project 77.54% <100.00%> (+<0.01%) ⬆️
inputsystem_Windows_6000.3 5.32% <0.00%> (-0.01%) ⬇️
inputsystem_Windows_6000.3_project 77.54% <100.00%> (+<0.01%) ⬆️
inputsystem_Windows_6000.4 5.33% <0.00%> (-0.01%) ⬇️
inputsystem_Windows_6000.4_project 77.55% <100.00%> (+<0.01%) ⬆️
inputsystem_Windows_6000.5 5.33% <0.00%> (-0.01%) ⬇️
inputsystem_Windows_6000.5_project 77.55% <100.00%> (+0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
Assets/Tests/InputSystem/CoreTests_Actions.cs 98.15% <100.00%> (+<0.01%) ⬆️
...nputsystem/InputSystem/Actions/InputActionState.cs 92.81% <100.00%> (+0.26%) ⬆️
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Collaborator

@jfreire-unity jfreire-unity left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice one-line fix with test reproducing the issue 🎉
Added some minor comments but no blockers.

// InputAction.cancel event handler (ISXB-1766). In this case we must skip controls associated with
// a device that is not connected to the system (Have deviceIndex < 0). We check this here to not
// cause side effects if aborting later in the call-chain.
if (!controls[controlIndex].device.added)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could a similar thing happen if a device were disabled?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought so which is why I extended the test to disable, enable, disable, enable but this seems to be fine. I have to admit why this is not clear and would also feel better by doing this symmetric. Should we explore making it symmetric or what do you think?

@u-pr-agent
Copy link
Contributor

u-pr-agent bot commented Nov 28, 2025

Persistent review updated to latest commit 3ebbcd6

@Pauliusd01

This comment was marked as off-topic.

@u-pr-agent

This comment was marked as off-topic.

@Pauliusd01
Copy link
Collaborator

Just updating that I am still looking at this, potentially found issues but need to nail down the repro first

Copy link
Collaborator

@Pauliusd01 Pauliusd01 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Found an issue with the user repro project, steps are:

Complete steps 2-11 from the ISXB-1767 bug -> instead of disconnecting the gamepad in isolation use WASD keyboard keys to move your character while you do it -> the gamepad disconnects and the console gets spammed with errors for each keyboard key pressed -> this persists even if you leave and reenter play mode

I wasn't able to reproduce this on a new project or without your changes so seems like a legit bug to me. I will paste the full errors to you over slack

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants