{"record":{"id":"5ccb3d2f695a477c","repo":"Unity-Technologies/ml-agents","slug":"the-behavior-name-needs-a-discrete-input-of-dime","errorCode":null,"errorMessage":"The behavior {name} needs a discrete input of dimension {_expected_shape} for (<number of agents>, <action size>) but received input of dimension {actions.discrete.shape}","messagePattern":"The behavior (.+?) needs a discrete input of dimension (.+?) for \\(<number of agents>, <action size>\\) but received input of dimension (.+?)","errorType":"validation","errorClass":"UnityActionException","httpStatus":null,"severity":"error","filePath":"ml-agents-envs/mlagents_envs/base_env.py","lineNumber":428,"sourceCode":"        return ActionTuple(continuous=_continuous, discrete=_discrete)\n\n    def _validate_action(\n        self, actions: ActionTuple, n_agents: int, name: str\n    ) -> ActionTuple:\n        \"\"\"\n        Validates that action has the correct action dim\n        for the correct number of agents and ensures the type.\n        \"\"\"\n        _expected_shape = (n_agents, self.continuous_size)\n        if actions.continuous.shape != _expected_shape:\n            raise UnityActionException(\n                f\"The behavior {name} needs a continuous input of dimension \"\n                f\"{_expected_shape} for (<number of agents>, <action size>) but \"\n                f\"received input of dimension {actions.continuous.shape}\"\n            )\n        _expected_shape = (n_agents, self.discrete_size)\n        if actions.discrete.shape != _expected_shape:\n            raise UnityActionException(\n                f\"The behavior {name} needs a discrete input of dimension \"\n                f\"{_expected_shape} for (<number of agents>, <action size>) but \"\n                f\"received input of dimension {actions.discrete.shape}\"\n            )\n        return actions\n\n    @staticmethod\n    def create_continuous(continuous_size: int) -> \"ActionSpec\":\n        \"\"\"\n        Creates an ActionSpec that is homogenously continuous\n        \"\"\"\n        return ActionSpec(continuous_size, ())\n\n    @staticmethod\n    def create_discrete(discrete_branches: Tuple[int]) -> \"ActionSpec\":\n        \"\"\"\n        Creates an ActionSpec that is homogenously discrete\n        \"\"\"","sourceCodeStart":410,"sourceCodeEnd":446,"githubUrl":"https://github.com/Unity-Technologies/ml-agents/blob/3ecb446f75d1e7400eb404c562dc005d3164cffc/ml-agents-envs/mlagents_envs/base_env.py#L410-L446","documentation":"BaseEnv._validate_action also checks ActionArgs.discrete against (n_agents, discrete_size) as declared by the behavior's BehaviorSpec; a mismatch raises UnityActionException. This mirrors the continuous check for the discrete action branch (branch sizes / number of branches).","triggerScenarios":"env.set_actions called with actions.discrete.shape != (number of deciding agents, discrete_size) — wrong number of rows, wrong total branch size, providing discrete arrays for a continuous-only behavior, or ints vs multi-dim mismatch.","commonSituations":"Policy emitting per-branch lists that weren't concatenated to one array; sending action vectors for all agents while only some are deciding; behavior's action space changed in Unity but trainer config still uses old branch sizes.","solutions":["Reshape discrete actions to (len(decision_steps), spec.action_spec.discrete_size) before set_actions.","For multi-branch behaviors, flatten per-branch outputs into one concatenated array of total discrete_size.","Re-read BehaviorSpec after any Unity behavior-parameter change and update the policy's output head accordingly."],"exampleFix":"# before\nenv.set_actions(name, ActionArgs(discrete=np.array([[0],[1]])))  # shape (2,1) but 2 branches\n# after\nimport numpy as np\n# two branches of size 2 and 3 -> discrete_size = 2\ndisc = np.array([[1, 0], [2, 1]], dtype=np.int32)  # shape (n_agents, 2)\nenv.set_actions(name, ActionArgs(discrete=disc))","handlingStrategy":"validation","validationCode":"import numpy as np\nn = len(decision_steps)\nds = behavior_spec.action_spec.discrete_size\ndisc = np.asarray(actions.discrete, dtype=np.int32)\nassert disc.shape == (n, ds), f\"need (n_agents, {ds}), got {disc.shape}\"","typeGuard":null,"tryCatchPattern":"try:\n    env.set_actions(name, ActionArgs(discrete=disc))\nexcept UnityActionException as e:\n    print(e)  # reshape to expected (n_agents, discrete_size) and retry once\n    raise","preventionTips":["Concatenate multi-branch discrete outputs into one (n, discrete_size) array","Re-read BehaviorSpec after changing Unity behavior parameters","Don't send discrete arrays for continuous-only behaviors (and vice versa)"],"tags":["python","ml-agents","action-space","shape-mismatch","discrete-actions"],"backgroundTag":"shape-mismatch","analyzedSha":"3ecb446f75d1e7400eb404c562dc005d3164cffc","analyzedAt":"2026-09-02T16:33:12.832Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T21:17:11.164Z"}