apache/cassandra · critical · FSReadError

FSReadError

Error message

FSReadError

What it means

CompressedSequentialWriter needs the current file channel position (e.g. to align to a compression chunk start). If the underlying FileChannel.position() call fails with an IOException, the writer wraps it in FSReadError carrying the file path, aborting the write because the on-disk position is essential to compressed chunk bookkeeping.

Source

Thrown at src/java/org/apache/cassandra/io/compress/CompressedSequentialWriter.java:179

    /**
     * Creates the {@link ChecksumWriter} for the chunk and full-file checksums. Invoked from the constructor,
     * so overrides must not read subclass fields.
     */
    protected ChecksumWriter createChecksumWriter()
    {
        return new ChecksumWriter(new DataOutputStream(Channels.newOutputStream(channel)));
    }

    @Override
    public long getOnDiskFilePointer()
    {
        try
        {
            return fchannel.position();
        }
        catch (IOException e)
        {
            throw new FSReadError(e, getPath());
        }
    }

    /**
     * Get a quick estimation on how many bytes have been written to disk
     *
     * It should for the most part be exactly the same as getOnDiskFilePointer()
     */
    @Override
    public long getEstimatedOnDiskBytesWritten()
    {
        return chunkOffset;
    }

    @Override
    public void flush()
    {
        throw new UnsupportedOperationException();

View on GitHub (pinned to 88fd0f6a0e)

Solutions

  1. Check the node/system logs and the wrapped IOException cause for the real OS error (EIO, EBADF, ENOSPC)
  2. Verify the data/commitlog disk health (dmesg, smartctl) and fix or replace the failing volume
  3. Run nodetool scrub/verify on affected SSTables and let failed flushes retry after the disk is healthy
  4. If it stems from a closed-channel bug, check for concurrent close of the writer and serialize writer lifecycle per file

Example fix

// before
// disk swapped under a live node -> fchannel.position() throws IOException -> FSReadError
// after
// ensure stable storage and run:
nodetool drain
# fix/replace disk, restart Cassandra; failed SSTables recovered via scrub
nodetool scrub ks tbl
Defensive patterns

Strategy: retry

Validate before calling

// Before writes, verify the data volume is healthy and writable
Files.isWritable(Paths.get(cassandraDataDir));
# dmesg | grep -i 'I/O error'

Try / catch

try {
    writer.getOnDiskFilePointer();
} catch (FSReadError e) {
    logger.error("Channel position failed for {}", e.getPath(), e.getCause());
    // fail the write; let Cassandra's flush executor retry after disk recovery
}

Prevention

When it happens

Trigger: Calling getOnDiskFilePointer()/seekToChunkStart() on a CompressedSequentialWriter whose file channel is broken: disk I/O error, file descriptor closed or invalidated (e.g. disk replaced, handle closed by another thread), or an OS-level error reading the channel's offset.

Common situations: Disk hardware failures or full/failed volumes during compaction or memtable flush; file handles closed unexpectedly after a disk swap; container environments where the storage backing SSTables becomes unavailable mid-write.

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/e8d63225d6b90347. Report an issue: GitHub.