{"record":{"id":"799e980127c8b876","repo":"Unity-Technologies/ml-agents","slug":"observation-did-not-have-the-expected-shape-got","errorCode":null,"errorMessage":"Observation did not have the expected shape - got {obs.shape} but expected {expected_shape}","messagePattern":"Observation did not have the expected shape - got (.+?) but expected (.+?)","errorType":"exception","errorClass":"UnityObservationException","httpStatus":null,"severity":"error","filePath":"ml-agents-envs/mlagents_envs/rpc_utils.py","lineNumber":227,"sourceCode":"                f\"Observation at index={obs_index} for agent with \"\n                f\"id={agent_info.id} didn't match the ObservationSpec. \"\n                f\"Expected shape {expected_obs_shape} but got {agent_obs_shape}.\"\n            )\n\n\n@timed\ndef _observation_to_np_array(\n    obs: ObservationProto, expected_shape: Optional[Iterable[int]] = None\n) -> np.ndarray:\n    \"\"\"\n    Converts observation proto into numpy array of the appropriate size.\n    :param obs: observation proto to be converted\n    :param expected_shape: optional shape information, used for sanity checks.\n    :return: processed numpy array of observation from environment\n    \"\"\"\n    if expected_shape is not None:\n        if list(obs.shape) != list(expected_shape):\n            raise UnityObservationException(\n                f\"Observation did not have the expected shape - got {obs.shape} but expected {expected_shape}\"\n            )\n    expected_channels = obs.shape[0]\n    if obs.compression_type == COMPRESSION_TYPE_NONE:\n        img = np.array(obs.float_data.data, dtype=np.float32)\n        img = np.reshape(img, obs.shape)\n        return img\n    else:\n        img = process_pixels(\n            obs.compressed_data, expected_channels, list(obs.compressed_channel_mapping)\n        )\n        # Compare decompressed image size to observation shape and make sure they match\n        if list(obs.shape) != list(img.shape):\n            raise UnityObservationException(\n                f\"Decompressed observation did not have the expected shape - \"\n                f\"decompressed had {img.shape} but expected {obs.shape}\"\n            )\n        return img","sourceCodeStart":209,"sourceCodeEnd":245,"githubUrl":"https://github.com/Unity-Technologies/ml-agents/blob/3ecb446f75d1e7400eb404c562dc005d3164cffc/ml-agents-envs/mlagents_envs/rpc_utils.py#L209-L245","documentation":"UnityObservationException raised by _observation_to_np_array when an observation proto's declared shape (obs.shape) doesn't equal the expected_shape from the ObservationSpec. The library validates before converting to numpy to give a clearer error than raw reshape failures.","triggerScenarios":"_process_maybe_compressed_observation converting an ObservationProto whose obs.shape differs from the expected_shape passed from the BehaviorSpec — spec/data disagreement from Unity.","commonSituations":"Behavior parameters (vector observation size, camera resolution) changed in Unity after the Python side cached the spec; mismatched ml-agents versions; multiple agents in one scene configured differently despite sharing a behavior name.","solutions":["Close and relaunch UnityEnvironment to refresh the BehaviorSpec.","Ensure every agent with the same behavior name has identical observation sizes (camera resolution, stacking, vec obs size).","Align com.unity.ml-agents and mlagents-envs package versions and rebuild.","Reset the environment after any editor-side changes (env.reset()) before stepping."],"exampleFix":"// before\n# editor changed Vector Observation Space Size from 8 to 12 mid-session\nenv.step()  # got [12] but expected [8]\n// after\nenv.close(); env = UnityEnvironment(...)  # spec refreshed to [12]","handlingStrategy":"try-catch","validationCode":"from mlagents_envs_envs import nothing  # check specs before stepping\n\ndef obs_specs_match(env, behavior, expected_shapes):\n    specs = env.behavior_specs[behavior].observation_specs\n    return [tuple(s.shape) for s in specs] == expected_shapes","typeGuard":null,"tryCatchPattern":"from mlagents_envs.exception import UnityObservationException\n\ntry:\n    env.step()\nexcept UnityObservationException as e:\n    if \"did not have the expected shape\" in str(e):\n        env.close()\n        env = UnityEnvironment(file_name=env_path)\n        env.reset()","preventionTips":["Restart the env after changing Vector Observation size or camera resolution in Unity.","Keep all agents with the same behavior identically configured.","Align com.unity.ml-agents and mlagents-envs versions.","Print env.behavior_specs after connect to confirm shapes match your trainer's expectations."],"tags":["python","unity-ml-agents","observation","shape-mismatch"],"backgroundTag":"observation-shape-mismatch","analyzedSha":"3ecb446f75d1e7400eb404c562dc005d3164cffc","analyzedAt":"2026-09-02T16:33:12.832Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T21:17:11.164Z"}