{"record":{"id":"d2d411cd4ad38776","repo":"apache/hadoop","slug":"not-allow-to-remove-an-inner-node-d2d411","errorCode":null,"errorMessage":"Not allow to remove an inner node: {}","messagePattern":"Not allow to remove an inner node: (.+?)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/net/NetworkTopologyWithNodeGroup.java","lineNumber":232,"sourceCode":"        }\n      }\n      if(LOG.isDebugEnabled()) {\n        LOG.debug(\"NetworkTopology became:\\n\" + this.toString());\n      }\n    } finally {\n      netlock.writeLock().unlock();\n    }\n  }\n\n  /** Remove a node\n   * Update node counter and rack counter if necessary\n   * @param node node to be removed; can be null\n   */\n  @Override\n  public void remove(Node node) {\n    if (node==null) return;\n    if( node instanceof InnerNode ) {\n      throw new IllegalArgumentException(\n          \"Not allow to remove an inner node: \"+NodeBase.getPath(node));\n    }\n    LOG.info(\"Removing a node: \"+NodeBase.getPath(node));\n    netlock.writeLock().lock();\n    try {\n      if (clusterMap.remove(node)) {\n        Node nodeGroup = getNode(node.getNetworkLocation());\n        if (nodeGroup == null) {\n          nodeGroup = factory.newInnerNode(node.getNetworkLocation());\n        }\n        InnerNode rack = (InnerNode)getNode(nodeGroup.getNetworkLocation());\n        if (rack == null) {\n          numOfRacks--;\n        }\n      }\n      if(LOG.isDebugEnabled()) {\n        LOG.debug(\"NetworkTopology became:\\n\" + this.toString());\n      }","sourceCodeStart":214,"sourceCodeEnd":250,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/net/NetworkTopologyWithNodeGroup.java#L214-L250","documentation":"NetworkTopologyWithNodeGroup.remove(Node) keeps the base-class contract: only leaf nodes can be removed. Inner nodes (racks and nodegroups) are structural and managed by the topology, so an InnerNode argument throws IllegalArgumentException before the write lock is taken.","triggerScenarios":"Calling remove(node) with a node instanceof InnerNode — a nodegroup/rack object from getNode(), or a mock extending InnerNode/InnerNodeWithNodeGroup.","commonSituations":"Node-group cluster tooling that resolves targets by path and removes without a type check; tests stubbing Node with an InnerNode base.","solutions":["Remove the leaf datanodes individually; nodegroup and rack levels clean up automatically","Guard with !(node instanceof InnerNode) before remove()","Rebuild the topology object if you need a full reset"],"exampleFix":"// before\ntopology.remove(nodeByPath); // could be an InnerNode\n\n// after\nif (!(nodeByPath instanceof InnerNode)) {\n  topology.remove(nodeByPath);\n}","handlingStrategy":"validation","validationCode":"if (!(node instanceof InnerNode)) {\n  topologyWithNodeGroup.remove(node);\n}","typeGuard":"static boolean isRemovableLeaf(Node n) {\n  return n != null && !(n instanceof InnerNode);\n}","tryCatchPattern":null,"preventionTips":["Type-check nodes from path lookups before remove() in node-group clusters too","Drain nodegroups by removing their member datanodes"],"tags":["hadoop-common","network-topology","nodegroup","invalid-argument"],"backgroundTag":"inner-node-rejected","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-23T01:17:44.959Z"}