Unity-Technologies/ml-agents · error · NullReferenceException

No parent indices set

Error message

No parent indices set

What it means

PoseExtractor.GetParentIndex returns the parent index of a body part but throws NullReferenceException when the internal m_ParentIndices array was never initialized. This means Setup() was never called (or was called with null) before querying the pose hierarchy. The library throws this to surface an ordering/lifecycle bug rather than silently returning a wrong parent index.

Source

Thrown at com.unity.ml-agents/Runtime/Sensors/PoseExtractor.cs:149

        /// <summary>
        /// Number of total poses in the hierarchy (read-only).
        /// </summary>
        public int NumPoses
        {
            get { return m_ModelSpacePoses?.Length ?? 0; }
        }

        /// <summary>
        /// Get the parent index of the body at the specified index.
        /// </summary>
        /// <param name="index">The index of the body whose parent index is to be retrieved.</param>
        /// <returns>The parent index of the body at the specified index.</returns>
        public int GetParentIndex(int index)
        {
            if (m_ParentIndices == null)
            {
                throw new NullReferenceException("No parent indices set");
            }

            return m_ParentIndices[index];
        }

        /// <summary>
        /// Set whether the pose at the given index is enabled or disabled for observations.
        /// </summary>
        /// <param name="index">The index of the pose to enable or disable.</param>
        /// <param name="val">Whether the pose is enabled (true) or disabled (false).</param>
        public void SetPoseEnabled(int index, bool val)
        {
            m_PoseEnabled[index] = val;
        }

        /// <summary>
        /// Returns whether the pose at the given index is enabled for observations.
        /// </summary>

View on GitHub (pinned to 3ecb446f75)

Solutions

  1. Ensure Setup(parentIndices) is called (with a valid array whose first element is -1) in your PoseExtractor subclass constructor or initialization path before any observation is taken.
  2. Check the call order: any code using GetParentIndex/parent must run after Setup, e.g. after the sensor is added to the Agent.
  3. Debug why Setup was skipped — e.g. an overridden Setup that doesn't call base.Setup, or a conditional initialization branch that never executed.

Example fix

// before
public MyPoseExtractor() { }
public int Parent(int i) => GetParentIndex(i); // throws: m_ParentIndices null
// after
public MyPoseExtractor()
{
    Setup(new[] { -1, 0, 0 }); // root first, then parents
}
public int Parent(int i) => GetParentIndex(i);
Defensive patterns

Strategy: validation

Validate before calling

if (extractor == null || extractor.GetParentIndexOrNull == null) { /* Setup() not called yet */ }
// wrap: expose parent indices via a property and check before use
bool ready = extractor.NumPoses > 0; // only true after Setup

Type guard

static bool IsPoseExtractorReady(PoseExtractor e) => e != null && e.NumPoses > 0;

Prevention

When it happens

Trigger: Calling GetParentIndex (directly or via the parent property) on a PoseExtractor subclass whose Setup(parentIndices) was never invoked, or whose constructor/sensor failed to call Setup before the first observation step.

Common situations: Writing a custom Sensor/PoseProvider subclass and forgetting to call Setup with the parent-index array in the constructor or initialization; calling GetParentIndex before the first sensor reset; a subclass overriding Setup incorrectly so the base method never runs.

Related errors


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