{"record":{"id":"e77eb8c9262fac65","repo":"apache/cassandra","slug":"invalid-sstable-file-name-cannot-extract-keysp","errorCode":null,"errorMessage":"Invalid sstable file ${name}: cannot extract keyspace and table name from %s; make sure the sstable is in the proper sub-directories","messagePattern":"Invalid sstable file (.+?): cannot extract keyspace and table name from (.+?); make sure the sstable is in the proper sub-directories","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/io/sstable/Descriptor.java","lineNumber":365,"sourceCode":"        if (!sstableDirMatcher.find(0))\n        {\n            sstableDirMatcher = LEGACY_SSTABLE_DIR_PATTERN.matcher(file.toString());\n        }\n\n        if (sstableDirMatcher.find(0))\n        {\n            keyspaceName = sstableDirMatcher.group(\"keyspace\");\n            tableName = sstableDirMatcher.group(\"tableName\");\n            String indexName = sstableDirMatcher.group(\"indexName\");\n            if (indexName != null)\n            {\n                tableName = String.format(\"%s.%s\", tableName, indexName);\n            }\n        }\n        else if (validateDirs)\n        {\n            logger.debug(\"Could not extract keyspace/table info from sstable directory {}\", file.toString());\n            throw invalidSSTable(name, String.format(\"cannot extract keyspace and table name from %s; make sure the sstable is in the proper sub-directories\", file));\n        }\n\n        return Pair.create(new Descriptor(info.version, parentOf(name, file), keyspaceName, tableName, info.id), info.component);\n    }\n\n    /**\n     * Parse a sstable filename, extracting both the {@code Descriptor} and {@code Component} part.\n     *\n     * @param file     the {@code File} object for the filename to parse.\n     * @param keyspace The keyspace name of the file. If <code>null</code>, then the keyspace name will be extracted\n     *                 from the directory path.\n     * @param table    The table name of the file. If <code>null</code>, then the table name will be extracted from the\n     *                 directory path.\n     * @return a pair of the descriptor and component corresponding to the provided {@code file}.\n     * @throws IllegalArgumentException if the provided {@code file} does point to a valid sstable filename. This could\n     *                                  mean either that the filename doesn't look like a sstable file, or that it is for an old and unsupported\n     *                                  versions.\n     */","sourceCodeStart":347,"sourceCodeEnd":383,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/io/sstable/Descriptor.java#L347-L383","documentation":"Newer Cassandra layouts store sstables in keyspace/table subdirectories, and fromFileWithComponent derives the keyspace and table names from the file's path. When validateDirs is true and the directory structure does not yield both names, this invalidSSTable exception is thrown, telling you the sstable is not in the proper sub-directories.","triggerScenarios":"Descriptor.fromFileWithComponent(file, validateDirs=true) on an sstable sitting in a flat data directory, a backup/restore location, or a manually moved path without the expected data/<keyspace>/<table>-<uuid>/ layout.","commonSituations":"Manual sstable copies after backup/restore that flatten the directory tree; moving sstables between nodes without preserving layout; running sstable utilities on files extracted to a temp directory.","solutions":["Move the sstable back into the proper data/<keyspace>/<table>-<id>/ sub-directory layout.","Pass validateDirs=false if you can supply keyspace/table another way (use the non-validating overload carefully).","Use the official backup/restore (e.g. medusa, snapshots) tooling that preserves the directory structure.","Rename the file and place it under the target table's directory matching the name-derived keyspace/table."],"exampleFix":"// before\n/var/lib/cassandra/data/md-1g-big-Data.db           // flat path -> thrown\n// after\n/var/lib/cassandra/data/myks/mytable-md-1g-big-Data.db  // proper keyspace/table sub-dirs","handlingStrategy":"validation","validationCode":"File dir = file.getParentFile();\n// require .../data/<keyspace>/<table[-uuid]>/<sstable>\nboolean ok = dir != null && dir.getParentFile() != null && dir.getParentFile().getParentFile() != null\n          && dir.getParentFile().getParentFile().getName().equals(\"data\");","typeGuard":null,"tryCatchPattern":"try { Pair<Descriptor, Component> p = Descriptor.fromFileWithComponent(file, true); }\ncatch (Throwable e) { if (e.getMessage() != null && e.getMessage().contains(\"cannot extract keyspace and table name\")) { /* restore proper dir layout */ } else throw e; }","preventionTips":["Always restore backups preserving the data/<keyspace>/<table>/ directory tree.","Use snapshot/restore tooling instead of manual file copies.","Run sstable utilities only on files inside the live data directories.","Validate directory layout before any offline sstable processing."],"tags":["sstable","descriptor","directory-layout","filename-parsing"],"backgroundTag":"path-is-not-a-directory","analyzedSha":"88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1","analyzedAt":"2026-09-10T07:29:22.284Z","contentChangedAt":"2026-09-10T07:29:22.284Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}