{"record":{"id":"19169a944f1671be","repo":"alibaba/arthas","slug":"current-node-is-root","errorCode":null,"errorMessage":"current node is root.","messagePattern":"current node is root\\.","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/com/taobao/arthas/core/view/TreeView.java","lineNumber":140,"sourceCode":"    public TreeView begin(String data) {\n        Node n = current.find(data);\n        if (n != null) {\n            current = n;\n        } else {\n            current = new Node(current, data);\n        }\n        current.markBegin();\n        return this;\n    }\n\n    /**\n     * 结束一个分支节点\n     *\n     * @return this\n     */\n    public TreeView end() {\n        if (current.isRoot()) {\n            throw new IllegalStateException(\"current node is root.\");\n        }\n        current.markEnd();\n        current = current.parent;\n        return this;\n    }\n\n    /**\n     * 结束一个分支节点,并带上备注\n     *\n     * @return this\n     */\n    public TreeView end(String mark) {\n        if (current.isRoot()) {\n            throw new IllegalStateException(\"current node is root.\");\n        }\n        current.markEnd().mark(mark);\n        current = current.parent;\n        return this;","sourceCodeStart":122,"sourceCodeEnd":158,"githubUrl":"https://github.com/alibaba/arthas/blob/21cf2e9ba52b305290be7223b980ff504bb9cb5b/core/src/main/java/com/taobao/arthas/core/view/TreeView.java#L122-L158","documentation":"TreeView.end() throws IllegalStateException when the current node is the root node — meaning there is no open branch to close. TreeView builds a tree imperatively: start() opens a branch (descends), end() closes it (ascends to parent). Calling end() more times than start() at the top level underflows to the root, which has no parent.","triggerScenarios":"Calling treeView.end() when the number of end() calls has already matched the number of start() calls, returning current to the root, and one more end() is issued.","commonSituations":"A mismatched start()/end() pair in custom command rendering code; a loop that calls end() unconditionally; refactoring that removed a start() but left its end(); calling end() on a freshly constructed TreeView that only has a root.","solutions":["Audit the TreeView construction code and ensure every end() has a matching preceding start().","Track branch depth with a counter and only call end() when depth > 0.","Use try/finally around start()/end() pairs to guarantee balance even on early returns."],"exampleFix":"// before: unbalanced — one extra end()\nTreeView tv = new TreeView(true, \"root\");\ntv.start(\"branch1\").end().end(); // second end() throws\n\n// after: balanced\ntreeView tv = new TreeView(true, \"root\");\ntv.start(\"branch1\").end();","handlingStrategy":"validation","validationCode":"// Track depth to avoid over-calling end()\nint depth = 0;\ntreeView.start(\"branch\"); depth++;\n// ... render ...\nif (depth > 0) { treeView.end(); depth--; }","typeGuard":null,"tryCatchPattern":"try {\n    treeView.end();\n} catch (IllegalStateException e) {\n    if (e.getMessage().contains(\"root\")) {\n        // already at root — nothing to close, ignore or log\n    } else { throw e; }\n}","preventionTips":["Maintain a depth counter that mirrors start/end calls.","Wrap each branch in try/finally to guarantee a matching end()."],"tags":["arthas","tree-view","logic-error","rendering"],"backgroundTag":null,"analyzedSha":"21cf2e9ba52b305290be7223b980ff504bb9cb5b","analyzedAt":"2026-08-14T00:57:07.243Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}