{"record":{"id":"7837c26da28ae1e3","repo":"Unity-Technologies/ml-agents","slug":"unsupported-sensor-with-specs-obs-spec","errorCode":null,"errorMessage":"Unsupported Sensor with specs {obs_spec}","messagePattern":"Unsupported Sensor with specs (.+?)","errorType":"exception","errorClass":"UnityTrainerException","httpStatus":null,"severity":"error","filePath":"ml-agents/mlagents/trainers/torch_entities/utils.py","lineNumber":186,"sourceCode":"            ModelUtils._check_resolution_for_encoder(\n                shape[1], shape[2], vis_encode_type\n            )\n            return (visual_encoder_class(shape[1], shape[2], shape[0], h_size), h_size)\n        # VECTOR\n        if dim_prop in ModelUtils.VALID_VECTOR_PROP:\n            return (VectorInput(shape[0], normalize), shape[0])\n        # VARIABLE LENGTH\n        if dim_prop in ModelUtils.VALID_VAR_LEN_PROP:\n            return (\n                EntityEmbedding(\n                    entity_size=shape[1],\n                    entity_num_max_elements=shape[0],\n                    embedding_size=attention_embedding_size,\n                ),\n                0,\n            )\n        # OTHER\n        raise UnityTrainerException(f\"Unsupported Sensor with specs {obs_spec}\")\n\n    @staticmethod\n    def create_input_processors(\n        observation_specs: List[ObservationSpec],\n        h_size: int,\n        vis_encode_type: EncoderType,\n        attention_embedding_size: int,\n        normalize: bool = False,\n    ) -> Tuple[nn.ModuleList, List[int]]:\n        \"\"\"\n        Creates visual and vector encoders, along with their normalizers.\n        :param observation_specs: List of ObservationSpec that represent the observation dimensions.\n        :param action_size: Number of additional un-normalized inputs to each vector encoder. Used for\n            conditioning network on other values (e.g. actions for a Q function)\n        :param h_size: Number of hidden units per layer excluding attention layers.\n        :param attention_embedding_size: Number of hidden units per attention layer.\n        :param vis_encode_type: Type of visual encoder to use.\n        :param unnormalized_inputs: Vector inputs that should not be normalized, and added to the vector","sourceCodeStart":168,"sourceCodeEnd":204,"githubUrl":"https://github.com/Unity-Technologies/ml-agents/blob/3ecb446f75d1e7400eb404c562dc005d3164cffc/ml-agents/mlagents/trainers/torch_entities/utils.py#L168-L204","documentation":"ModelUtils.get_encoder_for_obs raises UnityTrainerException when an ObservationSpec matches none of the supported categories (visual with translational-equivariance dims, plain vector, or entity/variable-length). ML-Agents only knows how to build input processors for those observation shapes; anything else is unsupported.","triggerScenarios":"create_input_processors encountering an ObservationSpec whose dimension properties (e.g. unrecognized combinations of DimensionProperty.TRANSLATIONAL_EQUIVARIANCE/SEMANTIC/none) or rank do not match the visual, vector, or entity patterns it handles.","commonSituations":"Custom sensors emitting unusual observation shapes/DimensionProperty combinations; Unity sensors added from packages (e.g. Grid sensor) in versions where ML-Agents had no encoder for them; migrating environments to newer mlagents-envs with new dimension property values.","solutions":["Use a supported sensor type (CameraSensor, VectorSensor, or Entity sensor) that emits standard ObservationSpecs","Fix the custom sensor's observation spec (rank and DimensionProperty values) to match a supported pattern: visual = rank 3 with TRANSLATIONAL_EQUIVARIANCE on H/W, vector = rank 1 or [N,1]","Check mlagents version compatibility with the sensor package emitting the observation","Flatten/convert exotic observations into a VectorSensor in your Unity code before training"],"exampleFix":"// before (custom sensor spec)\nobs_spec = ObservationSpec(shape=(4,4), dim_props=(NONE, NONE))  # rank-2, unsupported\n// after\nobs_spec = ObservationSpec(shape=(16,), dim_props=(NONE,))  # rank-1 vector, supported","handlingStrategy":"type-guard","validationCode":"from mlagents_envs.base_env import DimensionProperty\ndef supported(spec) -> bool:\n    if len(spec.shape) == 3 and spec.dimension_property[1:] == (DimensionProperty.TRANSLATIONAL_EQUIVARIANCE,)*2:\n        return True  # visual\n    return len(spec.shape) in (1, 2)  # vector\nassert all(supported(s) for s in behavior_spec.observation_specs)","typeGuard":"def is_supported_obs_spec(spec) -> bool:\n    dp = spec.dimension_property or (DimensionProperty.UNSPECIFIED,) * len(spec.shape)\n    visual = len(spec.shape) == 3 and dp[1:] == (DimensionProperty.TRANSLATIONAL_EQUIVARIANCE, DimensionProperty.TRANSLATIONAL_EQUIVARIANCE)\n    vector = len(spec.shape) == 1 or (len(spec.shape) == 2 and spec.shape[1] == 1)\n    return visual or vector","tryCatchPattern":"try:\n    processors = ModelUtils.create_input_processors(obs_specs, h, enc, norm)\nexcept UnityTrainerException as e:\n    logger.error(f\"Unsupported observation: {e}\")\n    raise SystemExit(\"Replace the sensor emitting the unsupported ObservationSpec\")","preventionTips":["Stick to CameraSensor, VectorSensor, or Entity sensors","Ensure custom sensors declare correct rank and DimensionProperty values","Test ObservationSpec compatibility when adding sensor packages"],"tags":["python","mlagents","observations","unsupported-sensor"],"backgroundTag":"unsupported-sensor-spec","analyzedSha":"3ecb446f75d1e7400eb404c562dc005d3164cffc","analyzedAt":"2026-09-02T16:33:12.832Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T21:17:11.164Z"}