{"record":{"id":"8d535c3e34e073d8","repo":"OtterMind/Chat2DB","slug":"selected-sql-directory-root-cannot-be-deleted","errorCode":null,"errorMessage":"Selected SQL directory root cannot be deleted","messagePattern":"Selected SQL directory root cannot be deleted","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"warning","filePath":"chat2db-community-server/chat2db-community-jcef/src/main/java/ai/chat2db/community/jcef/handler/biz/SqlDirectoryTreeStore.java","lineNumber":220,"sourceCode":"        }\n        Path realTarget = movedTarget.toRealPath(LinkOption.NOFOLLOW_LINKS);\n        if (!realTarget.startsWith(root)) {\n            throw new IllegalArgumentException(\"Path is outside of the selected SQL directory\");\n        }\n\n        String parentRelativePath = toRelativePath(root, parent);\n        Map<String, Object> result = new HashMap<>();\n        result.put(\"renamedNode\", toNode(rootToken, root, realTarget));\n        result.put(\"parentRelativePath\", parentRelativePath);\n        result.put(\"children\", listChildren(rootToken, parentRelativePath));\n        return result;\n    }\n\n    static Map<String, Object> deleteChild(String rootToken, String relativePath) throws IOException {\n        Path root = getRoot(rootToken);\n        Path target = resolveInRoot(root, relativePath);\n        if (target.equals(root)) {\n            throw new IllegalArgumentException(\"Selected SQL directory root cannot be deleted\");\n        }\n        if (Files.isSymbolicLink(target)) {\n            throw new IllegalArgumentException(\"Symbolic links are not supported\");\n        }\n\n        boolean file = Files.isRegularFile(target, LinkOption.NOFOLLOW_LINKS);\n        boolean directory = Files.isDirectory(target, LinkOption.NOFOLLOW_LINKS);\n        if (!file && !directory) {\n            throw new IllegalArgumentException(\"Selected path is not available\");\n        }\n        Path parent = target.getParent();\n        moveToTrash(target);\n\n        String parentRelativePath = toRelativePath(root, parent);\n        Map<String, Object> result = new HashMap<>();\n        result.put(\"parentRelativePath\", parentRelativePath);\n        result.put(\"children\", listChildren(rootToken, parentRelativePath));\n        return result;","sourceCodeStart":202,"sourceCodeEnd":238,"githubUrl":"https://github.com/OtterMind/Chat2DB/blob/5ee1e990e73fbcae1969dc554be254fedb3ab888/chat2db-community-server/chat2db-community-jcef/src/main/java/ai/chat2db/community/jcef/handler/biz/SqlDirectoryTreeStore.java#L202-L238","documentation":"Thrown by SqlDirectoryTreeStore.deleteChild() when the target path equals the root path. The root directory is managed by the rootToken lifecycle and cannot be deleted through the child-deletion API — deleting it would orphan the rootToken and break all tree references. The root is unregistered only when the session closes or the directory is explicitly closed.","triggerScenarios":"Invoked via delete-sql-directory-child JCEF action when relativePath is empty or resolves to the root itself. The frontend sent a delete request for the root node, or the relativePath was computed as empty string (which resolves to root in resolveInRoot).","commonSituations":"Frontend allows the user to trigger delete on the root tree node; the relativePath is '' matching root; a UI bug or keyboard shortcut sends the root node to the delete handler.","solutions":["On the frontend, disable delete for the root node (check if relativePath is empty)","Show the root node as non-deletable in the tree UI with a distinct visual treatment","Handle the error response and inform the user that the root directory cannot be deleted from within the tree"],"exampleFix":"// before: delete enabled on all nodes\nfunction onDelete(node) {\n  deleteChild(node.rootToken, node.relativePath);\n}\n\n// after: skip root node\nfunction onDelete(node) {\n  if (node.relativePath === '' || node.relativePath === ':') {\n    showError('The root directory cannot be deleted here');\n    return;\n  }\n  deleteChild(node.rootToken, node.relativePath);\n}","handlingStrategy":"validation","validationCode":"// Before calling deleteChild, verify the node is not the root\nif (relativePath == null || relativePath.isEmpty()) {\n    throw new IllegalArgumentException(\"Cannot delete the root directory\");\n}\nSqlDirectoryTreeStore.deleteChild(rootToken, relativePath);","typeGuard":null,"tryCatchPattern":"try {\n    Map<String, Object> result = SqlDirectoryTreeStore.deleteChild(rootToken, relativePath);\n    ResponseBuilder.buildSuccessJcef(Map.of(\"data\", result), callback);\n} catch (IllegalArgumentException e) {\n    callback.failure(400, e.getMessage());\n}","preventionTips":["Disable the delete action for the root node in the frontend tree UI","Check if relativePath is empty before sending the delete request","Show the root node with a non-deletable visual indicator"],"tags":["sql-directory","delete","user-input","business-rule"],"backgroundTag":null,"analyzedSha":"5ee1e990e73fbcae1969dc554be254fedb3ab888","analyzedAt":"2026-08-14T07:05:03.077Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}