{"record":{"id":"1469ff1958720b4c","repo":"apache/hadoop","slug":"cannot-delete-root-path-1469ff","errorCode":null,"errorMessage":"Cannot delete root path","messagePattern":"Cannot delete root path","errorType":"exception","errorClass":"PathIOException","httpStatus":null,"severity":"error","filePath":"hadoop-tools/hadoop-aliyun/src/main/java/org/apache/hadoop/fs/aliyun/oss/AliyunOSSFileSystem.java","lineNumber":251,"sourceCode":"   * attempt to continue with the delete operation: deleting root\n   * directories is never allowed. This method simply implements\n   * the policy of when to return an exit code versus raise an exception.\n   * @param isEmptyDir empty directory or not\n   * @param recursive recursive flag from command\n   * @return a return code for the operation\n   * @throws PathIOException if the operation was explicitly rejected.\n   */\n  private boolean rejectRootDirectoryDelete(boolean isEmptyDir,\n      boolean recursive) throws IOException {\n    LOG.info(\"oss delete the {} root directory of {}\", bucket, recursive);\n    if (isEmptyDir) {\n      return true;\n    }\n    if (recursive) {\n      return false;\n    } else {\n      // reject\n      throw new PathIOException(bucket, \"Cannot delete root path\");\n    }\n  }\n\n  private void createFakeDirectoryIfNecessary(Path f) throws IOException {\n    String key = pathToKey(f);\n    if (StringUtils.isNotEmpty(key) && !exists(f)) {\n      LOG.debug(\"Creating new fake directory at {}\", f);\n      mkdir(pathToKey(f.getParent()));\n    }\n  }\n\n  @Override\n  public FileStatus getFileStatus(Path path) throws IOException {\n    Path qualifiedPath = path.makeQualified(uri, workingDir);\n    String key = pathToKey(qualifiedPath);\n\n    // Root always exists\n    if (key.length() == 0) {","sourceCodeStart":233,"sourceCodeEnd":269,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-tools/hadoop-aliyun/src/main/java/org/apache/hadoop/fs/aliyun/oss/AliyunOSSFileSystem.java#L233-L269","documentation":"Thrown by AliyunOSSFileSystem.rejectRootDirectoryDelete(): a delete targeted the bucket root ('/'), the bucket is not empty, and recursive=false. Deleting an entire bucket's contents implicitly is destructive, so the connector raises PathIOException(bucket, \"Cannot delete root path\") instead. (An empty root returns true; recursive=true is allowed to proceed.)","triggerScenarios":"Calling fs.delete(new Path(\"oss://bucket/\"), false) — directly or via 'hadoop fs -rm oss://bucket' — when any object exists in the bucket; generic cleanup code that walks to the filesystem root and deletes what it sees.","commonSituations":"Recursive cleanup routines that reach the root after deleting children; tools that call delete on an empty-string path; guarding against accidental bucket wipes in production data lakes.","solutions":["Target the specific subdirectory to delete (oss://bucket/prefix) instead of the bucket root","If wiping the bucket is truly intended, pass recursive=true with extreme care, or delete via the OSS console/API","Constrain cleanup code to never construct a delete on the root path; assert path depth before calling delete"],"exampleFix":"// before\nfs.delete(new Path(\"oss://my-bucket/\"), false); // Cannot delete root path\n\n// after\nfs.delete(new Path(\"oss://my-bucket/dataset/\"), true);","handlingStrategy":"validation","validationCode":"Path toDelete = path;\nif (toDelete.isRoot() || toDelete.depth() <= 1) {\n  throw new IOException(\"Refusing to delete bucket root: \" + toDelete);\n}\nfs.delete(toDelete, true);","typeGuard":null,"tryCatchPattern":"catch (PathIOException e) { /* root-delete guard tripped: never widen; fix the caller's path construction */ throw e; }","preventionTips":["Assert path depth before constructing delete calls in cleanup code","Point cleanup at concrete dataset prefixes, never at oss://bucket or oss://bucket/"],"tags":["aliyun-oss","delete","root-path","safety-guard","hadoop-connector"],"backgroundTag":"filesystem-root-delete-rejected","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}