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
- Match com.unity.ml-agents and mlagents-envs versions and rebuild the Unity executable.
- Restart UnityEnvironment after changing camera resolutions or sensor setups in the editor.
- Verify with a stock sample environment to rule out environment-specific corruption.
- 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
- Match Unity/Python ml-agents versions; rebuild after upgrades.
- Relaunch the env after camera resolution changes.
- Confirm camera sensor width/height in Unity match expected ObservationSpec.
- Sanity-check with a sample environment to rule out data corruption.
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
- Observation at index={obs_index} for agent with id={agent_in
- Observation did not have the expected shape - got {obs.shape
- Compressed observation and its mapping had different number
- Invalid Compressed Channel Mapping: the mapping {mappings} d
- Invalid Compressed Channel Mapping: the mapping has index la
AI-assisted analysis of Unity-Technologies/ml-agents@3ecb446f75 (2026-09-02).
Data as JSON: /api/errors/e7484c40f5a759ba.
Report an issue: GitHub.