{"record":{"id":"a4b9f2e4f0935db9","repo":"apache/seatunnel","slug":"directory-s-is-not-empty","errorCode":null,"errorMessage":"Directory: %s is not empty.","messagePattern":"Directory: (.+?) is not empty\\.","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"seatunnel-connectors-v2/connector-file/connector-file-sftp/src/main/java/org/apache/seatunnel/connectors/seatunnel/file/sftp/system/SFTPFileSystem.java","lineNumber":383,"sourceCode":"            fileStat = getFileStatus(channel, absolute);\n        } catch (FileNotFoundException e) {\n            // file not found, no need to delete, return true\n            return false;\n        }\n        if (!fileStat.isDirectory()) {\n            boolean status = true;\n            try {\n                channel.rm(pathName);\n            } catch (SftpException e) {\n                status = false;\n            }\n            return status;\n        } else {\n            boolean status = true;\n            FileStatus[] dirEntries = listStatus(channel, absolute);\n            if (dirEntries != null && dirEntries.length > 0) {\n                if (!recursive) {\n                    throw new IOException(String.format(E_DIR_NOTEMPTY, file));\n                }\n                for (int i = 0; i < dirEntries.length; ++i) {\n                    delete(channel, new Path(absolute, dirEntries[i].getPath()), recursive);\n                }\n            }\n            try {\n                channel.rmdir(pathName);\n            } catch (SftpException e) {\n                status = false;\n            }\n            return status;\n        }\n    }\n\n    /**\n     * Convenience method, so that we don't open a new connection when using this method from within\n     * another method. Otherwise every API invocation incurs the overhead of opening/closing a TCP\n     * connection.","sourceCodeStart":365,"sourceCodeEnd":401,"githubUrl":"https://github.com/apache/seatunnel/blob/cf67b549a7a6c35fa0beb12d83c62892427ea919/seatunnel-connectors-v2/connector-file/connector-file-sftp/src/main/java/org/apache/seatunnel/connectors/seatunnel/file/sftp/system/SFTPFileSystem.java#L365-L401","documentation":"delete() refuses to remove a directory that still contains entries when recursive=false, throwing IOException formatted with E_DIR_NOTEMPTY. This mirrors Hadoop FileSystem semantics: non-recursive deletes of non-empty directories are rejected rather than silently truncating data.","triggerScenarios":"fs.delete(dirPath, false) on a directory that contains at least one file or subdirectory (as reported by listStatus).","commonSituations":"Cleanup code assuming delete() clears whole trees but passing recursive=false; overwriting an existing non-empty output directory during job setup; leftover files from a previous failed run.","solutions":["Pass recursive=true: fs.delete(path, true)","Empty the directory first (delete each child) then delete the directory","Pick a fresh output path or enable overwrite-aware cleanup before the job","Verify the directory is actually empty (fs.listStatus(path).length == 0) before a non-recursive delete"],"exampleFix":"// before\nfs.delete(new Path(\"/tmp/out\"), false);\n// after\nfs.delete(new Path(\"/tmp/out\"), true);","handlingStrategy":"validation","validationCode":"Path dir = new Path(\"/tmp/out\");\nif (fs.exists(dir) && fs.getFileStatus(dir).isDirectory()\n        && fs.listStatus(dir).length > 0 && !recursive) {\n    throw new IllegalStateException(\"Refusing non-recursive delete of non-empty \" + dir);\n}","typeGuard":null,"tryCatchPattern":"try {\n    fs.delete(dir, false);\n} catch (IOException e) {\n    if (String.valueOf(e.getMessage()).contains(\"is not empty\")) {\n        fs.delete(dir, true); // escalate to recursive\n    } else { throw e; }\n}","preventionTips":["Always pass an explicit recursive flag matching intent","Clean output directories before job start","Make deletes idempotent in retry logic"],"tags":["sftp","directory","delete"],"backgroundTag":"directory-not-found","analyzedSha":"cf67b549a7a6c35fa0beb12d83c62892427ea919","analyzedAt":"2026-09-10T21:44:55.265Z","contentChangedAt":"2026-09-10T21:44:55.265Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}