{"record":{"id":"c5128228ef376e4f","repo":"apache/cassandra","slug":"cannot-safely-construct-descriptor-for-segment-ei","errorCode":null,"errorMessage":"Cannot safely construct descriptor for segment, either from its name or its header: ","messagePattern":"Cannot safely construct descriptor for segment, either from its name or its header: ","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/db/commitlog/CommitLogArchiver.java","lineNumber":289,"sourceCode":"    public void maybeRestoreArchive()\n    {\n        if (Strings.isNullOrEmpty(restoreDirectories))\n            return;\n\n        for (String dir : restoreDirectories.split(DELIMITER))\n        {\n            File[] files = new File(dir).tryList();\n            if (files == null)\n            {\n                throw new RuntimeException(\"Unable to list directory \" + dir);\n            }\n            for (File fromFile : files)\n            {\n                CommitLogDescriptor fromHeader = CommitLogDescriptor.fromHeader(fromFile, DatabaseDescriptor.getEncryptionContext());\n                CommitLogDescriptor fromName = CommitLogDescriptor.isValid(fromFile.name()) ? CommitLogDescriptor.fromFileName(fromFile.name()) : null;\n                CommitLogDescriptor descriptor;\n                if (fromHeader == null && fromName == null)\n                    throw new IllegalStateException(\"Cannot safely construct descriptor for segment, either from its name or its header: \" + fromFile.path());\n                else if (fromHeader != null && fromName != null && !fromHeader.equalsIgnoringCompression(fromName))\n                    throw new IllegalStateException(String.format(\"Cannot safely construct descriptor for segment, as name and header descriptors do not match (%s vs %s): %s\", fromHeader, fromName, fromFile.path()));\n                else if (fromName != null && fromHeader == null)\n                    throw new IllegalStateException(\"Cannot safely construct descriptor for segment, as name descriptor implies a version that should contain a header descriptor, but that descriptor could not be read: \" + fromFile.path());\n                else if (fromHeader != null)\n                    descriptor = fromHeader;\n                else descriptor = fromName;\n\n                if (descriptor.version > CommitLogDescriptor.current_version)\n                    throw new IllegalStateException(\"Unsupported commit log version: \" + descriptor.version);\n\n                if (descriptor.compression != null)\n                {\n                    try\n                    {\n                        CompressionParams.createCompressor(descriptor.compression);\n                    }\n                    catch (ConfigurationException e)","sourceCodeStart":271,"sourceCodeEnd":307,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/db/commitlog/CommitLogArchiver.java#L271-L307","documentation":"Thrown by maybeRestoreArchive() when an archived commit log segment can neither be identified from its filename nor from its binary header (both CommitLogDescriptor.fromHeader and fromFileName return null). Cassandra refuses to guess and aborts the restore rather than replaying an unidentified segment.","triggerScenarios":"A file in a restore directory is not a recognizable commit log segment: corrupted header, truncated file (header not yet written), foreign/random file placed in the restore dir, or a filename not matching the CommitLogSegment pattern.","commonSituations":"Manually copying stray files (e.g. backup notes, partial uploads) into the restore directory; interrupted archive copy leaving a 0-byte segment; incompatible/foreign segment files from another storage engine.","solutions":["Remove or move out non-commit-log and unidentifiable files from the restore directory.","Re-copy the affected segment from the archive; verify the copy is complete (compare sizes/checksums with the archived original).","Check the file has a valid header: commit log segments written by Cassandra always begin with a descriptor header unless truncated.","Confirm the file name matches CommitLog-<version>-<id>.log pattern."],"exampleFix":"# before (restore dir contains a stray file)\n/mnt/restore/notes.txt\n# after\nmv /mnt/restore/notes.txt /tmp/ && ls /mnt/restore\n# only CommitLog-*.log segment files remain","handlingStrategy":"validation","validationCode":"for (File f : restoreDir.listFiles()) {\n    boolean nameOk = CommitLogDescriptor.isValid(f.getName());\n    boolean headerOk = CommitLogDescriptor.fromHeader(f, DatabaseDescriptor.getEncryptionContext()) != null;\n    if (!nameOk && !headerOk)\n        log.warn(\"Unidentifiable file in restore dir, remove it: \" + f);\n}","typeGuard":null,"tryCatchPattern":"try { archiver.maybeRestoreArchive(); }\ncatch (IllegalStateException e) {\n    if (e.getMessage().startsWith(\"Cannot safely construct descriptor\"))\n        log.error(\"Remove/re-copy unidentifiable segment files in restore dirs\", e);\n    throw e;\n}","preventionTips":["Only copy commit log segment files into restore directories","Verify completed copies with checksums before starting the node","Clean out stale/foreign files from restore directories before each restore"],"tags":["cassandra","commitlog","restore","corruption"],"backgroundTag":"internal-invariant-violation","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"}