Unity-Technologies/ml-agents · error · UnityObservationException

Decompressed observation did not have the expected shape - d

Error message

Decompressed observation did not have the expected shape - decompressed had {img.shape} but expected {obs.shape}

What it means

UnityObservationException raised by _observation_to_np_array after decompressing a compressed observation: the reconstructed numpy image's shape doesn't match obs.shape declared in the proto. It means Unity's compressed payload (e.g. PNG) doesn't decode to the dimensions it claims.

Source

Thrown at ml-agents-envs/mlagents_envs/rpc_utils.py:241

    :return: processed numpy array of observation from environment
    """
    if expected_shape is not None:
        if list(obs.shape) != list(expected_shape):
            raise UnityObservationException(
                f"Observation did not have the expected shape - got {obs.shape} but expected {expected_shape}"
            )
    expected_channels = obs.shape[0]
    if obs.compression_type == COMPRESSION_TYPE_NONE:
        img = np.array(obs.float_data.data, dtype=np.float32)
        img = np.reshape(img, obs.shape)
        return img
    else:
        img = process_pixels(
            obs.compressed_data, expected_channels, list(obs.compressed_channel_mapping)
        )
        # Compare decompressed image size to observation shape and make sure they match
        if list(obs.shape) != list(img.shape):
            raise UnityObservationException(
                f"Decompressed observation did not have the expected shape - "
                f"decompressed had {img.shape} but expected {obs.shape}"
            )
        return img


@timed
def _process_maybe_compressed_observation(
    obs_index: int,
    observation_spec: ObservationSpec,
    agent_info_list: Collection[AgentInfoProto],
) -> np.ndarray:
    shape = cast(Tuple[int, int, int], observation_spec.shape)
    if len(agent_info_list) == 0:
        return np.zeros((0, shape[0], shape[1], shape[2]), dtype=np.float32)

    try:
        batched_visual = [

View on GitHub (pinned to 3ecb446f75)

Solutions

  1. Match com.unity.ml-agents and mlagents-envs versions and rebuild the Unity executable.
  2. Restart UnityEnvironment after changing camera resolutions or sensor setups in the editor.
  3. Verify with a stock sample environment to rule out environment-specific corruption.
  4. Check that no custom Unity-side code overrides the camera grab dimensions (CameraSensor width/height must match ObservationSpec).

Example fix

// before
# camera resolution changed in editor; old env still running
img_shape = (3, 84, 84); declared = (3, 96, 96)
// after
env.close(); env = UnityEnvironment(...)  # spec and pixels agree
Defensive patterns

Strategy: try-catch

Try / catch

from mlagents_envs.exception import UnityObservationException

try:
    env.step()
except UnityObservationException as e:
    if "Decompressed observation" in str(e):
        env.close()
        env = UnityEnvironment(file_name=env_path)  # refresh spec; verify versions

Prevention

When it happens

Trigger: process_pixels decompressing obs.compressed_data into an image whose shape != obs.shape — e.g. PNG bytes with different width/height/channels than declared, often from version-skewed serialization or corrupted data.

Common situations: Mismatched ml-agents Unity/Python versions changing compression conventions; camera resolution changed in Unity without relaunching the env; corrupted image data over gRPC; custom grab implementations sending wrong-size frames.

Related errors


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