Android: NotSupportedException while resolving binding 'Move:<Keyboard>/rightArrow[;Keyboard&Mouse]'

Unity 2019.4.20f1, Input System 1.1.1, Android

According to Unity Cloud Diagnostics, my game randomly starts throwing the following exceptions after the game ran without error for several hours before.

This problem occurs on Android phones and I’m unable to reproduce the problem locally.

  • Any idea how to reproduce it?
  • Any idea how to fix/workaround it?
  • What is the error actually telling me and how severe is the problem?
NotSupportedException while resolving binding 'Move:<Keyboard>/rightArrow[;Keyboard&Mouse]' in action map 'InputActions (UnityEngine.InputSystem.InputActionAsset):Player'
NotSupportedException while resolving binding 'Navigate:<Keyboard>/rightArrow[Keyboard&Mouse]' in action map 'InputActions (UnityEngine.InputSystem.InputActionAsset):UI'
NotSupportedException while resolving binding 'Move:<Keyboard>/rightArrow[;Keyboard&Mouse]' in action map 'InputActions (UnityEngine.InputSystem.InputActionAsset):Player'
NotSupportedException while resolving binding 'Navigate:<Keyboard>/rightArrow[Keyboard&Mouse]' in action map 'InputActions (UnityEngine.InputSystem.InputActionAsset):UI'

This is my “Player Input” configuration:

I do want the player to be able to attach a gamepad the phone and play with gamepad, that’s why I turned on “Auto-Switch”.

The actual exception should be in the log right after the message that there was an exception. That one should come with a full callstack.

Thank you for your answer.

The following exception that is logged in Cloud Diagnostics along the “NotSupportedException while resolving binding” issue:

NotSupportedException: Control count per binding cannot exceed byte.MaxValue=255
UnityEngine.InputSystem.InputActionState+<>c.<SaveAndResetState>b__121_1 () (at <00000000000000000000000000000000>:0)
UnityEngine.InputSystem.InputBindingCompositeContext+<get_controls>d__2.System.Collections.IEnumerable.GetEnumerator () (at <00000000000000000000000000000000>:0)
UnityEngine.InputSystem.InputActionMap.ResolveBindings () (at <00000000000000000000000000000000>:0)
UnityEngine.InputSystem.InputActionMap.LazyResolveBindings () (at <00000000000000000000000000000000>:0)
UnityEngine.InputSystem.InputActionState.OnDeviceChange (UnityEngine.InputSystem.InputDevice device, UnityEngine.InputSystem.InputDeviceChange change) (at <00000000000000000000000000000000>:0)
UnityEngine.InputSystem.InputManager.AddDevice (UnityEngine.InputSystem.InputDevice device) (at <00000000000000000000000000000000>:0)
UnityEngine.InputSystem.InputManager.AddDevice (UnityEngine.InputSystem.Utilities.InternedString layout, System.Int32 deviceId, System.String deviceName, UnityEngine.InputSystem.Layouts.InputDeviceDescription deviceDescription, UnityEngine.InputSystem.InputDevice+DeviceFlags deviceFlags, UnityEngine.InputSystem.Utilities.InternedString variants) (at <00000000000000000000000000000000>:0)
UnityEngine.InputSystem.InputManager.AddDevice (UnityEngine.InputSystem.Layouts.InputDeviceDescription description, System.Boolean throwIfNoLayoutFound, System.String deviceName, System.Int32 deviceId, UnityEngine.InputSystem.InputDevice+DeviceFlags deviceFlags) (at <00000000000000000000000000000000>:0)
UnityEngine.InputSystem.InputManager.OnNativeDeviceDiscovered (System.Int32 deviceId, System.String deviceDescriptor) (at <00000000000000000000000000000000>:0)
System.Action`2[T1,T2].Invoke (T1 arg1, T2 arg2) (at <00000000000000000000000000000000>:0)
System.Action`2:Invoke(T1, T2)

Please note that the issue occurs on different Android devices with different OS’s. The exception and callstack don’t help me further. Can you extract from it where the problem lies?

Something must be adding more and more devices to the point where a single binding ends up resolving to more than 255 controls. Looking at the binding, it would seem that by that point 255 keyboards have been added.

The most common cause for this is script code that manually does AddDevice over and over and never removes the devices. But the stack above looks like the device was actually reported by the Android backend. Which makes me suspect something must be misbehaving there.

Android has a weird thing where the type of a device is a flag. And all kinds of devices end up reporting themselves as keyboards. But even then, for this to be the cause, it’d have to report a new keyboard device over and over and over.

Another thing that puzzles me is that looking at your PlayerInput and action configuration, even having a thousand keyboards shouldn’t matter. With control schemes and auto-switch being used, it should always track only the actively used devices and thus never try to resolve a <Keyboard>/rightArrow from all keyboards that have been reported.

Is the above PlayerInput action setup the only way you are using those actions? Or by chance, do you happen to have “Generate C# Class” on and are using that one as well?

Thank you for your reply and help.

I checked it, we don’t call AddDevice anywhere in the code.

We’re using “Generate C# Class”. Here is how we use it…

public class UIButtonShortcutId : ScriptableObject
{
    InputActions m_InputActions = null;

    void OnEnable()
    {
        m_InputActions = InputActionsUtility.Create();
        m_InputActions.Enable();
    }

    void OnDisable()
    {
        InputActionsUtility.Destroy(m_InputActions);
    }
public class HeroInput : MonoBehaviour
{
    InputActions m_InputActions;

    void Awake()
    {
        m_InputActions = InputActionsUtility.Create();
        m_InputActions.Enable();
    }

    void OnDestroy()
    {
        InputActionsUtility.Destroy(m_InputActions);
    }

Here is the InputActionsUtility code. It outputs the number of InputActions each time a level was loaded. It’s 4 InputActions in a level and 2 InputActions in the mainmenu. Switching levels doesn’t increase the number of InputActions, there doesn’t seem to be a leak, I just tested it.

public static class InputActionsUtility
{
   static int s_Count;

   [RuntimeInitializeOnLoadMethod]
   static void RuntimeInitializeOnLoadMethod()
   {
       s_Count = 0;
       Loading.scenesLoaded -= OnScenesLoaded;
       Loading.scenesLoaded += OnScenesLoaded;
   }

   static void OnScenesLoaded()
   {
       Dbg.Log(null, $"{s_Count} InputActions created");
   }

   public static InputActions Create()
   {
       var obj = new InputActions();
       s_Count++;
       return obj;
   }

   public static void Destroy(InputActions obj)
   {
       if (obj == null || obj.asset == null) return;
       s_Count--;

       obj.Disable();

       // If we call Dispose() in OnDisable() while the editor exists playmode,
       // Unity outputs an error that you must use DestroyImmediate instead.
       // So this is our workaround here.
       if (Application.isPlaying)
           obj.Dispose();
   }
}

Ah, so that would explain the “why are actions trying to grab all keyboards instead of one” part. The code generated by “Generate C# Class” will by default resolve against the full list of devices available through InputSystem.devices. This can be restricted manually through the devices property but unlike PlayerInput, the code here doesn’t do any control scheme switching. So with 256 keyboards in InputSystem.devices, “/rightArrow” would resolve to 256 controls.

In general, when using PlayerInput, it’s best not to also use “Generate C# Class”.

However, the real bug would still be the fact there are >255 keyboards in the first place. It very strongly looks like something in the Android backend causing that. A bug report for this one would be appreciated.

Thank you for the reply.

  1. How can I workaround the issue? You mention I could restrict the available devices through a “devices property”, but how? The game is heavily relying on the “Generate C# Class” thing, it’s not an easy task for me to get rid of it.

  2. Is submitting a bug-report going to help, when I don’t have a project where you can reliably reproduce the issue? I’m not able to reproduce this issue at all for example. So far any bug-report I submitted without a 100% reproduction case didn’t lead to anything.

var actions = new MyGeneratedActions();
actions.devices = new InputDevice[] { Keyboard.current };

This is the part that unfortunately, compared to PlayerInput, has to be managed manually.

Ah, hmm, that indeed complicates things. I was under the impression that simply running the app for several hours inevitably leads to the problem. Is there by chance a pattern to the devices (brand?) on which the problem occurs?

The “Control count per binding cannot exceed byte.MaxValue=255” problem seems to occur on iPad7,11 with iOS 15.3.1 only, according to Unity Cloud Diagnostics.

I found the following warning in those reports that Cloud Diagnostics collected:

Received stylus event from a device which shouldn't have supported it. Check IsStylusTouchSupported implementation

This warning doesn’t come from our code, probably from Unity or InputSystem. Is it any helpful?

same bug on android with the InputSystem package 1.3.0, I use this code to enable android keyboards

06/02/2022 08:34:25] <Error>: NotSupportedException while resolving binding 'KeyboardPressAction:<keyboard>/<key>' in action map '<Unnamed Action Map>'
UnityEngine.InputSystem.InputAction:Enable()
Quattro.UnityInputs:Start()
[06/02/2022 08:34:25] <Exception>: NotSupportedException: Control count per binding cannot exceed byte.MaxValue=255
UnityEngine.InputSystem.InputActionState+BindingState.set_controlCount (System.Int32 value) (at <00000000000000000000000000000000>:0)
UnityEngine.InputSystem.InputBindingResolver.AddActionMap (UnityEngine.InputSystem.InputActionMap map) (at <00000000000000000000000000000000>:0)
UnityEngine.InputSystem.InputActionMap.ResolveBindings () (at <00000000000000000000000000000000>:0)
UnityEngine.InputSystem.InputAction.Enable () (at <00000000000000000000000000000000>:0)
Quattro.UnityInputs.Start () (at <00000000000000000000000000000000>:0)
UnityEngine.InputSystem.InputAction:Enable()
Quattro.UnityInputs:Start()

where UnityInputs:Start is :

 m_keyboardAction = new InputAction(name: "KeyboardPressAction", InputActionType.PassThrough,
            binding: "<keyboard>/<key>");
            m_keyboardAction.performed += callbackContext => KeyboardKeyPressPerformed(callbackContext.control as KeyControl);
            m_keyboardAction.Enable();

I get this error later too

[06/02/2022 03:31:26] <Error>: NotSupportedException while resolving binding 'KeyboardPressAction:<keyboard>/<key>' in action map '<Unnamed Action Map>'
UnityEngine.InputSystem.LowLevel.<>c__DisplayClass7_0:<set_onUpdate>b__0(NativeInputUpdateType, NativeInputEventBuffer*)
[06/02/2022 03:31:26] <Exception>: NotSupportedException: Control count per binding cannot exceed byte.MaxValue=255
UnityEngine.InputSystem.InputActionState+BindingState.set_controlCount (System.Int32 value) (at <00000000000000000000000000000000>:0)
UnityEngine.InputSystem.InputBindingResolver.AddActionMap (UnityEngine.InputSystem.InputActionMap map) (at <00000000000000000000000000000000>:0)
UnityEngine.InputSystem.InputActionMap.ResolveBindings () (at <00000000000000000000000000000000>:0)
UnityEngine.InputSystem.InputActionMap.LazyResolveBindings () (at <00000000000000000000000000000000>:0)
UnityEngine.InputSystem.InputActionState.OnDeviceChange (UnityEngine.InputSystem.InputDevice device, UnityEngine.InputSystem.InputDeviceChange change) (at <00000000000000000000000000000000>:0)
UnityEngine.InputSystem.InputManager.OnUpdate (UnityEngine.InputSystem.LowLevel.InputUpdateType updateType, UnityEngine.InputSystem.LowLevel.InputEventBuffer& eventBuffer) (at <00000000000000000000000000000000>:0)
UnityEngine.InputSystem.LowLevel.NativeInputRuntime+<>c__DisplayClass7_0.<set_onUpdate>b__0 (UnityEngineInternal.Input.NativeInputUpdateType updateType, UnityEngineInternal.Input.NativeInputEventBuffer* eventBufferPtr) (at <00000000000000000000000000000000>:0)
UnityEngine.InputSystem.LowLevel.<>c__DisplayClass7_0:<set_onUpdate>b__0(NativeInputUpdateType, NativeInputEventBuffer*)

I had to disable keyboards on android to stop the bug

How would I do that?