apache/cassandra · error · SegmentReadException

Encountered bad header at position %d of commit log %s, with

Error message

Encountered bad header at position %d of commit log %s, with bad position but valid CRC

What it means

readSyncMarker also validates the marker's next-segment offset: end must lie within [offset, reader.length()]. When CRC is valid but the target position is out of range, SegmentReadException(tolerable=false) is thrown ('bad position but valid CRC'). A valid checksum pointing outside the file means the segment is truncated or from a different configuration — replay cannot continue safely.

Source

Thrown at src/java/org/apache/cassandra/db/commitlog/CommitLogSegmentReader.java:210

            {
                logger.warn("Skipping sync marker CRC check at position {} (end={}, calculated crc={}) of commit log {}." +
                            "Using per-mutation CRC checks to ensure correctness...",
                            offset, end, crc.getValue(), reader.getPath());
                return end;
            }

            if (end != 0 || filecrc != 0)
            {
                String msg = String.format("Encountered bad header at position %d of commit log %s, with invalid CRC. " +
                             "The end of segment marker should be zero.", offset, reader.getPath());
                throw new SegmentReadException(msg, true);
            }
            return -1;
        }
        else if (end < offset || end > reader.length())
        {
            String msg = String.format("Encountered bad header at position %d of commit log %s, with bad position but valid CRC", offset, reader.getPath());
            throw new SegmentReadException(msg, false);
        }
        return end;
    }

    public static class SegmentReadException extends IOException
    {
        public final boolean invalidCrc;

        public SegmentReadException(String msg, boolean invalidCrc)
        {
            super(msg);
            this.invalidCrc = invalidCrc;
        }
    }

    public static class SyncSegment
    {
        /** the 'buffer' to replay commit log data from */

View on GitHub (pinned to 88fd0f6a0e)

Solutions

  1. Restore the complete, untruncated commit log files from backup.
  2. Match commitlog_segment_size_in_mb to the value used when the logs were written.
  3. Accept partial replay: remove/discard the truncated segment; run nodetool repair so replicas restore lost data.
  4. If only this node is affected, wipe commitlog/ and bootstrap/repair from peers.
Defensive patterns

Strategy: validation

Validate before calling

if (markerEnd > reader.length() || markerEnd < offset)
    throw new IOException("Segment truncated: marker end " + markerEnd + " outside file length " + reader.length());

Try / catch

try {
    replaySegment(file);
} catch (SegmentReadException e) {
    if (!e.tolerable) {
        logger.error("Truncated commit log {}: restore full file or accept loss and repair", file);
        // decide: abort vs. discard segment + nodetool repair
    }
}

Prevention

When it happens

Trigger: Replaying a commit log shorter than the recorded marker end (truncation, incomplete copy, restored partial file), or a segment written with a different segment size than the current configuration.

Common situations: Restoring only part of the commitlog directory from backup; rsync/scp interrupted mid-copy; mismatched cassandra.yaml commitlog_segment_size_in_mb between writer and replayer; deliberately trimmed files.

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10). Data as JSON: /api/errors/ecf016efede5b3c2. Report an issue: GitHub.