{"record":{"id":"7618c8c3bcdfd251","repo":"apache/cassandra","slug":"insufficient-permissions-on-directory-path","errorCode":null,"errorMessage":"Insufficient permissions on directory <path>","messagePattern":"Insufficient permissions on directory <path>","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/db/SSTableImporter.java","lineNumber":329,"sourceCode":"     *\n     * If srcPaths is empty, we create a lister that lists sstables in the data directories (deprecated use)\n     */\n    private List<Pair<Directories.SSTableLister, String>> getSSTableListers(Set<String> srcPaths)\n    {\n        List<Pair<Directories.SSTableLister, String>> listers = new ArrayList<>();\n\n        if (!srcPaths.isEmpty())\n        {\n            for (String path : srcPaths)\n            {\n                File dir = new File(path);\n                if (!dir.exists())\n                {\n                    throw new RuntimeException(String.format(\"Directory %s does not exist\", path));\n                }\n                if (!Directories.verifyFullPermissions(dir, path))\n                {\n                    throw new RuntimeException(\"Insufficient permissions on directory \" + path);\n                }\n                listers.add(Pair.create(cfs.getDirectories().sstableLister(dir, Directories.OnTxnErr.IGNORE).skipTemporary(true), path));\n            }\n        }\n        else\n        {\n            listers.add(Pair.create(cfs.getDirectories().sstableLister(Directories.OnTxnErr.IGNORE).skipTemporary(true), null));\n        }\n\n        return listers;\n    }\n\n    private static class MovedSSTable\n    {\n        private final Descriptor newDescriptor;\n        private final Descriptor oldDescriptor;\n        private final Set<Component> components;\n","sourceCodeStart":311,"sourceCodeEnd":347,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/db/SSTableImporter.java#L311-L347","documentation":"Before listing sstables for import, SSTableImporter calls Directories.verifyFullPermissions on each source directory. If the permissions are insufficient (not readable/writable/executable by the Cassandra user) it throws a RuntimeException. The importer must be able to read the sstables and interact with transaction log files, so weak permissions are rejected up front.","triggerScenarios":"Importing sstables from a directory owned by root or another user, or with restrictive mode bits (e.g. 0700 owned by another account), when running as the cassandra service user.","commonSituations":"Files copied into place with sudo/scp as root; backup restores where permissions were not preserved; sstables streamed from another cluster with different uid; SELinux/AppArmor restrictions.","solutions":["chown the directory and its contents to the user running Cassandra (usually cassandra:cassandra): `chown -R cassandra:cassandra <path>`","Grant full permissions for the Cassandra user: `chmod -R u+rwx <path>`","Verify with `sudo -u cassandra ls -la <path>` that the service user can read and traverse the directory","Check SELinux/AppArmor denials in audit logs if permissions look correct"],"exampleFix":"// before (shell)\n-rw------- root root /staging/sstables-00001.db\n// after\nchown -R cassandra:cassandra /staging && chmod -R u+rwX /staging","handlingStrategy":"validation","validationCode":"File dir = new File(path);\nif (!dir.canRead() || !dir.canWrite() || !dir.canExecute())\n    throw new IllegalStateException(\"Insufficient permissions for cassandra user on: \" + path);","typeGuard":"boolean isFullyAccessible(String p) { File d = new File(p); return d.isDirectory() && d.canRead() && d.canWrite() && d.canExecute(); }","tryCatchPattern":"try { importer.importNewSSTables(...); } catch (RuntimeException e) { if (e.getMessage() != null && e.getMessage().startsWith(\"Insufficient permissions\")) { /* chown/chmod and retry */ } else throw e; }","preventionTips":["Copy staged sstables as the cassandra service user, or chown immediately after transfer","Standardize staging directories with a provisioning script that sets ownership/modes","Check SELinux/AppArmor policies for import directories"],"tags":["sstable","import","permissions","storage"],"backgroundTag":"permission-denied","analyzedSha":"88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1","analyzedAt":"2026-09-10T07:29:22.284Z","contentChangedAt":"2026-09-10T07:29:22.284Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}