Unity-Technologies/ml-agents · error · UnityActionException

The behavior {name} needs a discrete input of dimension {_ex

Error message

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}

What it means

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).

Source

Thrown at ml-agents-envs/mlagents_envs/base_env.py:428

        return ActionTuple(continuous=_continuous, discrete=_discrete)

    def _validate_action(
        self, actions: ActionTuple, n_agents: int, name: str
    ) -> ActionTuple:
        """
        Validates that action has the correct action dim
        for the correct number of agents and ensures the type.
        """
        _expected_shape = (n_agents, self.continuous_size)
        if actions.continuous.shape != _expected_shape:
            raise UnityActionException(
                f"The behavior {name} needs a continuous input of dimension "
                f"{_expected_shape} for (<number of agents>, <action size>) but "
                f"received input of dimension {actions.continuous.shape}"
            )
        _expected_shape = (n_agents, self.discrete_size)
        if actions.discrete.shape != _expected_shape:
            raise UnityActionException(
                f"The behavior {name} needs a discrete input of dimension "
                f"{_expected_shape} for (<number of agents>, <action size>) but "
                f"received input of dimension {actions.discrete.shape}"
            )
        return actions

    @staticmethod
    def create_continuous(continuous_size: int) -> "ActionSpec":
        """
        Creates an ActionSpec that is homogenously continuous
        """
        return ActionSpec(continuous_size, ())

    @staticmethod
    def create_discrete(discrete_branches: Tuple[int]) -> "ActionSpec":
        """
        Creates an ActionSpec that is homogenously discrete
        """

View on GitHub (pinned to 3ecb446f75)

Solutions

  1. Reshape discrete actions to (len(decision_steps), spec.action_spec.discrete_size) before set_actions.
  2. For multi-branch behaviors, flatten per-branch outputs into one concatenated array of total discrete_size.
  3. Re-read BehaviorSpec after any Unity behavior-parameter change and update the policy's output head accordingly.

Example fix

# before
env.set_actions(name, ActionArgs(discrete=np.array([[0],[1]])))  # shape (2,1) but 2 branches
# after
import numpy as np
# two branches of size 2 and 3 -> discrete_size = 2
disc = np.array([[1, 0], [2, 1]], dtype=np.int32)  # shape (n_agents, 2)
env.set_actions(name, ActionArgs(discrete=disc))
Defensive patterns

Strategy: validation

Validate before calling

import numpy as np
n = len(decision_steps)
ds = behavior_spec.action_spec.discrete_size
disc = np.asarray(actions.discrete, dtype=np.int32)
assert disc.shape == (n, ds), f"need (n_agents, {ds}), got {disc.shape}"

Try / catch

try:
    env.set_actions(name, ActionArgs(discrete=disc))
except UnityActionException as e:
    print(e)  # reshape to expected (n_agents, discrete_size) and retry once
    raise

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of Unity-Technologies/ml-agents@3ecb446f75 (2026-09-02). Data as JSON: /api/errors/5ccb3d2f695a477c. Report an issue: GitHub.