{"record":{"id":"d441491407362082","repo":"apache/hadoop","slug":"cannot-remove-directory-f-it-is-not-empty","errorCode":null,"errorMessage":"Cannot remove directory {f}: It is not empty!","messagePattern":"Cannot remove directory (.+?): It is not empty!","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"hadoop-tools/hadoop-aliyun/src/main/java/org/apache/hadoop/fs/aliyun/oss/AliyunOSSFileSystem.java","lineNumber":212,"sourceCode":"  private boolean innerDelete(FileStatus status, boolean recursive)\n      throws IOException {\n    Path f = status.getPath();\n    String p = f.toUri().getPath();\n    FileStatus[] statuses;\n    // indicating root directory \"/\".\n    if (p.equals(\"/\")) {\n      statuses = listStatus(status.getPath());\n      boolean isEmptyDir = statuses.length <= 0;\n      return rejectRootDirectoryDelete(isEmptyDir, recursive);\n    }\n\n    String key = pathToKey(f);\n    if (status.isDirectory()) {\n      if (!recursive) {\n        // Check whether it is an empty directory or not\n        statuses = listStatus(status.getPath());\n        if (statuses.length > 0) {\n          throw new IOException(\"Cannot remove directory \" + f +\n              \": It is not empty!\");\n        } else {\n          // Delete empty directory without '-r'\n          key = AliyunOSSUtils.maybeAddTrailingSlash(key);\n          store.deleteObject(key);\n        }\n      } else {\n        store.deleteDirs(key);\n      }\n    } else {\n      store.deleteObject(key);\n    }\n\n    createFakeDirectoryIfNecessary(f);\n    return true;\n  }\n\n  /**","sourceCodeStart":194,"sourceCodeEnd":230,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-tools/hadoop-aliyun/src/main/java/org/apache/hadoop/fs/aliyun/oss/AliyunOSSFileSystem.java#L194-L230","documentation":"Thrown by AliyunOSSFileSystem.delete(): the target is a directory, recursive=false, and listStatus() on it returned one or more entries. Object stores cannot atomically delete a 'directory' with children in non-recursive mode, so the connector refuses with IOException(\"Cannot remove directory \" + f + \": It is not empty!\") to emulate POSIX rm semantics.","triggerScenarios":"Calling fs.delete(path, false) on an OSS prefix that contains objects or child prefixes; shell 'hadoop fs -rm oss://bucket/dir' (non-recursive default) where dir has children.","commonSituations":"Cleanup scripts ported from HDFS that used rm without -r on directories; assuming an empty directory exists when OSS still holds a zero-byte marker or hidden child keys (e.g., _SUCCESS, .crc files, or 'fake directory' markers from other tools).","solutions":["Pass recursive=true when the intent is to delete the whole subtree: fs.delete(path, true)","If it must be empty, list the children first and delete/move them, then delete the directory key","Check for non-obvious child keys (including zero-byte directory markers) with listStatus before assuming emptiness"],"exampleFix":"// before\nfs.delete(dirPath, /*recursive*/ false);\n\n// after\nfs.delete(dirPath, /*recursive*/ true);","handlingStrategy":"validation","validationCode":"FileStatus st = fs.getFileStatus(dir);\nif (st.isDirectory() && fs.listStatus(dir).length > 0) {\n  boolean recursive = /* user intent */ true;\n  if (!recursive) throw new IOException(\"Directory not empty: \" + dir);\n}\nfs.delete(dir, recursive);","typeGuard":null,"tryCatchPattern":"catch (IOException e) { if (e.getMessage().startsWith(\"Cannot remove directory\")) { /* escalate to delete(path, true) or delete children manually */ } throw e; }","preventionTips":["Always pass the recursive flag explicitly instead of defaulting to false for directories","Before 'empty-dir' deletes, list children to catch hidden marker/_SUCCESS objects"],"tags":["aliyun-oss","delete","directory-not-empty","hadoop-connector"],"backgroundTag":"delete-directory-not-empty","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}