{"record":{"id":"32b5109511d34555","repo":"Unity-Technologies/ml-agents","slug":"the-source-provided-had-nan-values","errorCode":null,"errorMessage":"The {source} provided had NaN values.","messagePattern":"The (.+?) provided had NaN values\\.","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"ml-agents-envs/mlagents_envs/rpc_utils.py","lineNumber":286,"sourceCode":"    return np.array(batched_visual, dtype=np.float32)\n\n\ndef _raise_on_nan_and_inf(data: np.array, source: str) -> np.array:\n    # Check for NaNs or Infinite values in the observation or reward data.\n    # If there's a NaN in the observations, the np.mean() result will be NaN\n    # If there's an Infinite value (either sign) then the result will be Inf\n    # See https://stackoverflow.com/questions/6736590/fast-check-for-nan-in-numpy for background\n    # Note that a very large values (larger than sqrt(float_max)) will result in an Inf value here\n    # Raise a Runtime error in the case that NaNs or Infinite values make it into the data.\n    if data.size == 0:\n        return data\n\n    d = np.mean(data)\n    has_nan = np.isnan(d)\n    has_inf = not np.isfinite(d)\n\n    if has_nan:\n        raise RuntimeError(f\"The {source} provided had NaN values.\")\n    if has_inf:\n        raise RuntimeError(f\"The {source} provided had Infinite values.\")\n\n\n@timed\ndef _process_rank_one_or_two_observation(\n    obs_index: int,\n    observation_spec: ObservationSpec,\n    agent_info_list: Collection[AgentInfoProto],\n) -> np.ndarray:\n    if len(agent_info_list) == 0:\n        return np.zeros((0,) + observation_spec.shape, dtype=np.float32)\n    try:\n        np_obs = np.array(\n            [\n                agent_obs.observations[obs_index].float_data.data\n                for agent_obs in agent_info_list\n            ],","sourceCodeStart":268,"sourceCodeEnd":304,"githubUrl":"https://github.com/Unity-Technologies/ml-agents/blob/3ecb446f75d1e7400eb404c562dc005d3164cffc/ml-agents-envs/mlagents_envs/rpc_utils.py#L268-L304","documentation":"RuntimeError raised by _raise_on_nan_and_inf when the mean of the data being processed (observation, reward, etc. from Unity) is NaN, indicating the environment sent non-numeric values. The library fails fast because NaNs would silently poison training.","triggerScenarios":"steps_from_proto or _process_rank_one_or_two_observation receiving data containing NaN — e.g. agent state diverged, sensor producing NaN in Unity, physics instability, or reward function dividing by zero.","commonSituations":"Unstable physics simulations (fast rotations, extreme forces) in Unity producing NaN transforms; custom sensors or reward functions with division by zero; uninitialized textures/cameras in the environment; corrupted observation floats.","solutions":["Inspect the Unity environment for unstable simulation (limit rigidbody velocities, clamp torques, use fixed timesteps) and fix NaN-producing sensors/rewards.","Use env.reset() to restart the episode and check if NaNs recur immediately or only after long rollouts.","Clamp observations/rewards Unity-side or in a wrapper before they reach the trainer.","Update com.unity.ml-agents and mlagents-envs to matching latest versions in case of a known serialization bug."],"exampleFix":"// before\n# Unity reward: reward = 1 / distance_to_target  -> inf/NaN when distance == 0\n// after\n# Unity C#: reward = distance_to_target > 1e-6 ? 1f / distance_to_target : 0f;","handlingStrategy":"try-catch","validationCode":"import numpy as np\n\ndef obs_clean(arr: np.ndarray) -> bool:\n    return np.isfinite(arr).all()","typeGuard":"import numpy as np\n\ndef has_no_nan(arr: np.ndarray) -> bool:\n    return not np.isnan(arr).any()","tryCatchPattern":"from mlagents_envs.exception import UnityException\nimport numpy as np\n\ntry:\n    env.step()\nexcept RuntimeError as e:\n    if \"had NaN values\" in str(e):\n        decision_steps, terminal_steps = env.reset()  # restart episode","preventionTips":["Fix Unity-side sources of NaN (unstable physics, div-by-zero rewards, broken sensors).","Clamp observations/rewards in Unity or a Python wrapper.","Call env.reset() after NaN to avoid poisoning downstream buffers.","Log which behavior/agent produced NaN to isolate the faulty scene component."],"tags":["python","unity-ml-agents","nan","numerical"],"backgroundTag":"nan-in-observation-data","analyzedSha":"3ecb446f75d1e7400eb404c562dc005d3164cffc","analyzedAt":"2026-09-02T16:33:12.832Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T21:17:11.164Z"}