{"record":{"id":"7bf05d7c8ca13e00","repo":"OtterMind/Chat2DB","slug":"selected-sql-directory-root-cannot-be-renamed","errorCode":null,"errorMessage":"Selected SQL directory root cannot be renamed","messagePattern":"Selected SQL directory root cannot be renamed","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":173,"sourceCode":"\n        String name = normalizeFileName(rawName, \"sql\");\n        Path realTarget = writeAvailableFile(root, parent, name, content == null ? \"\" : content);\n        if (!realTarget.startsWith(root)) {\n            throw new IllegalArgumentException(\"Path is outside of the selected SQL directory\");\n        }\n\n        Map<String, Object> result = new HashMap<>();\n        result.put(\"createdNode\", toNode(rootToken, root, realTarget));\n        result.put(\"children\", listChildren(rootToken, parentRelativePath));\n        return result;\n    }\n\n    static Map<String, Object> renameChild(String rootToken, String relativePath, String rawName)\n            throws IOException {\n        Path root = getRoot(rootToken);\n        Path source = resolveInRoot(root, relativePath);\n        if (source.equals(root)) {\n            throw new IllegalArgumentException(\"Selected SQL directory root cannot be renamed\");\n        }\n        if (Files.isSymbolicLink(source)) {\n            throw new IllegalArgumentException(\"Symbolic links are not supported\");\n        }\n\n        boolean file = Files.isRegularFile(source, LinkOption.NOFOLLOW_LINKS);\n        boolean directory = Files.isDirectory(source, LinkOption.NOFOLLOW_LINKS);\n        if (!file && !directory) {\n            throw new IllegalArgumentException(\"Selected path is not available\");\n        }\n        String sourceFileName = source.getFileName().toString();\n        String fallbackExtension = file ? getFileExtension(sourceFileName) : \"\";\n        String name = file ? normalizeExistingFileName(rawName, fallbackExtension)\n                : normalizeDirectoryName(rawName);\n        Path parent = source.getParent();\n        Path target = parent.resolve(name).normalize();\n        if (!target.startsWith(root)) {\n            throw new IllegalArgumentException(\"Path is outside of the selected SQL directory\");","sourceCodeStart":155,"sourceCodeEnd":191,"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#L155-L191","documentation":"Thrown by SqlDirectoryTreeStore.renameChild() when the source path equals the root path. The root directory is managed as an opaque token and cannot be renamed through this API — renaming it would invalidate all relativePath references in the tree and break the rootToken contract.","triggerScenarios":"Invoked via rename-sql-directory-child JCEF action when relativePath is empty or resolves to the root itself. The frontend sent a rename request for the root node, or the relativePath was computed incorrectly to match root.","commonSituations":"Frontend allows the user to enter rename mode on the root tree node; the relativePath is empty string '' (which resolves to root in resolveInRoot); a UI bug sends the root node to the rename action.","solutions":["On the frontend, disable rename for the root node (check if relativePath is empty or node is the root)","Show the root node as non-renameable in the tree UI","Handle the error response and inform the user that the root directory cannot be renamed"],"exampleFix":"// before: rename enabled on all nodes including root\nfunction onRename(node, newName) {\n  renameChild(node.rootToken, node.relativePath, newName);\n}\n\n// after: skip root node\nfunction onRename(node, newName) {\n  if (node.relativePath === '' || node.relativePath === ':') {\n    showError('The root directory cannot be renamed');\n    return;\n  }\n  renameChild(node.rootToken, node.relativePath, newName);\n}","handlingStrategy":"validation","validationCode":"// Before calling renameChild, verify the node is not the root\nif (relativePath == null || relativePath.isEmpty()) {\n    throw new IllegalArgumentException(\"Cannot rename the root directory\");\n}\nSqlDirectoryTreeStore.renameChild(rootToken, relativePath, rawName);","typeGuard":null,"tryCatchPattern":"try {\n    Map<String, Object> result = SqlDirectoryTreeStore.renameChild(rootToken, relativePath, name);\n    ResponseBuilder.buildSuccessJcef(Map.of(\"data\", result), callback);\n} catch (IllegalArgumentException e) {\n    callback.failure(400, e.getMessage());\n}","preventionTips":["Disable the rename action for the root node in the frontend tree UI","Check if relativePath is empty before sending the rename request","Show the root node with a non-renameable visual indicator"],"tags":["sql-directory","rename","user-input","business-rule"],"backgroundTag":null,"analyzedSha":"5ee1e990e73fbcae1969dc554be254fedb3ab888","analyzedAt":"2026-08-14T07:05:03.077Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}