apache/hadoop · error · IllegalArgumentException

${node}is not an ancestor of ${n}

Error message

${node}is not an ancestor of ${n}

What it means

IllegalArgumentException from InnerNodeImpl.getNextAncestorName(Node) when the node passed in is not a descendant of this inner node — i.e., n.getNetworkLocation() does not start with this node's path in the network topology tree. The method walks one level down from this node toward n, so it first asserts isAncestor(n); the message (note the missing space in the source: '<node>is not an ancestor of <n>') prints both nodes with their locations.

Source

Thrown at hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/net/InnerNodeImpl.java:115

  public boolean isAncestor(Node n) {
    return getPath(this).equals(NodeBase.PATH_SEPARATOR_STR) ||
      (n.getNetworkLocation()+NodeBase.PATH_SEPARATOR_STR).
      startsWith(getPath(this)+NodeBase.PATH_SEPARATOR_STR);
  }

  /** Judge if this node is the parent of node <i>n</i>.
   *
   * @param n a node
   * @return true if this node is the parent of <i>n</i>
   */
  public boolean isParent(Node n) {
    return n.getNetworkLocation().equals(getPath(this));
  }

  /* Return a child name of this node who is an ancestor of node <i>n</i> */
  public String getNextAncestorName(Node n) {
    if (!isAncestor(n)) {
      throw new IllegalArgumentException(
                                         this + "is not an ancestor of " + n);
    }
    String name = n.getNetworkLocation().substring(getPath(this).length());
    if (name.charAt(0) == PATH_SEPARATOR) {
      name = name.substring(1);
    }
    int index=name.indexOf(PATH_SEPARATOR);
    if (index != -1) {
      name = name.substring(0, index);
    }
    return name;
  }

  @Override
  public boolean add(Node n) {
    if (!isAncestor(n)) {
      throw new IllegalArgumentException(n.getName()
          + ", which is located at " + n.getNetworkLocation()

View on GitHub (pinned to 2add963021)

Solutions

  1. Call isAncestor(n) (or NetworkTopology.isAncestor) before getNextAncestorName and handle the false case
  2. Make the topology script deterministic and normalize locations to the '/a/b' form with a leading '/' and no trailing slash
  3. Log node.getNetworkLocation() for both nodes at the failure point to find which registration produced the divergent path

Example fix

// before
InnerNode inner = (InnerNode) node;
String child = inner.getNextAncestorName(n); // throws if n not under inner

// after
if (inner.isAncestor(n)) {
  String child = inner.getNextAncestorName(n);
} else {
  LOG.warn("{} not under {}; locations: {} vs {}", n.getName(), inner,
      n.getNetworkLocation(), inner.getNetworkLocation());
}
Defensive patterns

Strategy: validation

Validate before calling

if (!inner.isAncestor(n)) {
  throw new IllegalStateException("location mismatch: " + n.getNetworkLocation()
      + " not under " + inner.getNetworkLocation());
}

Try / catch

catch (IllegalArgumentException e) { /* '<node>is not an ancestor of <n>' */ log both network locations and re-register n under the correct parent; }

Prevention

When it happens

Trigger: Calling getNextAncestorName(n) where this node's path is '/default-rack' but n's network location is '/dc1/rack2'; a topology script returning inconsistent locations for the same node across calls; node locations missing the leading '/' so prefix comparison fails.

Common situations: Misconfigured or nondeterministic topology scripts (dfs.network.script / net.topology.script.file.name); nodes registered under different racks than the ones being searched; malformed network location strings from custom Node implementations.

Related errors


AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22). Data as JSON: /api/errors/3d9ee32de9fb30cf. Report an issue: GitHub.