{"record":{"id":"7fefef6bbef82fa4","repo":"apache/hadoop","slug":"path-7fefef","errorCode":null,"errorMessage":"{path}","messagePattern":"\\{path\\}","errorType":"exception","errorClass":"PathIsNotEmptyDirectoryException","httpStatus":null,"severity":"error","filePath":"hadoop-cloud-storage-project/hadoop-huaweicloud/src/main/java/org/apache/hadoop/fs/obs/OBSPosixBucketUtils.java","lineNumber":353,"sourceCode":"    Path f = status.getPath();\n    String key = OBSCommonUtils.pathToKey(owner, f);\n\n    if (!status.isDirectory()) {\n      LOG.debug(\"delete: Path is a file\");\n      trashObjectIfNeed(owner, key);\n    } else {\n      LOG.debug(\"delete: Path is a directory: {} - recursive {}\", f,\n          recursive);\n      key = OBSCommonUtils.maybeAddTrailingSlash(key);\n      boolean isEmptyDir = OBSCommonUtils.isFolderEmpty(owner, key);\n      if (key.equals(\"\")) {\n        return OBSCommonUtils.rejectRootDirectoryDelete(\n            owner.getBucket(), isEmptyDir, recursive);\n      }\n      if (!recursive && !isEmptyDir) {\n        LOG.warn(\"delete: Path is not empty: {} - recursive {}\", f,\n            recursive);\n        throw new PathIsNotEmptyDirectoryException(f.toString());\n      }\n      if (isEmptyDir) {\n        LOG.debug(\n            \"delete: Deleting fake empty directory {} - recursive {}\",\n            f, recursive);\n        OBSCommonUtils.deleteObject(owner, key);\n      } else {\n        LOG.debug(\n            \"delete: Deleting objects for directory prefix {} to \"\n                + \"delete - recursive {}\", f, recursive);\n        trashFolderIfNeed(owner, key, f);\n      }\n    }\n\n    long endTime = System.currentTimeMillis();\n    LOG.debug(\"delete Path:{} thread:{}, timeUsedInMilliSec:{}\", f,\n        threadId, endTime - startTime);\n    return true;","sourceCodeStart":335,"sourceCodeEnd":371,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-cloud-storage-project/hadoop-huaweicloud/src/main/java/org/apache/hadoop/fs/obs/OBSPosixBucketUtils.java#L335-L371","documentation":"In the POSIX delete path, a directory is checked for contents with isFolderEmpty; delete(f, recursive=false) on a non-empty directory throws PathIsNotEmptyDirectoryException with the path string as the message. The bucket root (empty key) is refused separately, and an empty folder is deleted as a single object.","triggerScenarios":"fs.delete(dir, false) while dir contains objects or subfolders; cleanup routines that assumed non-recursive delete on object storage removes everything; partition drops without the recursive flag.","commonSituations":"Code ported from HDFS or local filesystems; concurrent writers adding content between the emptiness check and the delete; scheduled cleanup jobs configured non-recursive by default.","solutions":["Pass recursive=true when the whole tree must go: fs.delete(dir, true)","List and selectively delete children when only part of the content should be removed","Re-check directory contents on failure when a concurrent-writer race is plausible"],"exampleFix":"// before\nfs.delete(dir, false);\n\n// after\nfs.delete(dir, true);","handlingStrategy":"validation","validationCode":"if (fs.getFileStatus(dir).isDirectory() && fs.listStatus(dir).length > 0\n    && !recursive) {\n  throw new PathIsNotEmptyDirectoryException(dir.toString());\n}","typeGuard":"static boolean isEmptyDirectory(FileSystem fs, Path p) throws IOException {\n  return fs.getFileStatus(p).isDirectory() && fs.listStatus(p).length == 0;\n}","tryCatchPattern":"try {\n  fs.delete(dir, false);\n} catch (PathIsNotEmptyDirectoryException e) {\n  // content arrived concurrently: re-list and choose delete(dir, true) or skip\n}","preventionTips":["Pass recursive=true for full tree removal","Use explicit child listing for partial cleanup","Schedule deletes outside window where writers may still add content"],"tags":["hadoop","obs","posix","delete","directory-not-empty"],"backgroundTag":"directory-not-empty","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}