apache/cassandra · error · IllegalStateException

Filesystem block size must be a power of two for Direct IO.

Error message

Filesystem block size must be a power of two for Direct IO. Block size: %d

What it means

O_DIRECT writes must be aligned to the filesystem's logical block size, and Cassandra's direct compressed writer requires that size to be a power of two to compute aligned buffer arithmetic. If FileUtils.getBlockSize() returns a value that is not a power of two, the constructor throws this IllegalStateException. Like its sibling check, the txn proxy is aborted in the catch path since the caller never gets the writer reference to clean up.

Source

Thrown at src/java/org/apache/cassandra/io/compress/DirectCompressedSequentialWriter.java:115

                                            @Nullable File digestFile,
                                            SequentialWriterOption option,
                                            CompressionParams parameters,
                                            MetadataCollector sstableMetadataCollector,
                                            @Nullable CompressionDictionaryManager compressionDictionaryManager)
    {
        super(file, offsetsFile, digestFile, option, parameters, sstableMetadataCollector, compressionDictionaryManager, ExtendedOpenOption.DIRECT);

        // super() opened the O_DIRECT FileChannel and allocated parent buffers; if anything below throws
        // the caller never gets a reference to clean them up, so abort the txn proxy ourselves.
        try
        {
            this.blockSize = FileUtils.getBlockSize(file.parent());
            if (blockSize <= 0)
                throw new IllegalStateException("Unable to determine filesystem block size for Direct IO. " +
                                                "Block size: " + blockSize);

            if (!BitUtil.isPowerOfTwo(blockSize))
                throw new IllegalStateException("Filesystem block size must be a power of two for Direct IO. " +
                                                "Block size: " + blockSize);

            int configuredSize = DatabaseDescriptor.getDirectWriteBufferSize().toBytes();
            int maxChunkWrite = parameters.getSstableCompressor().initialCompressedBufferLength(parameters.chunkLength());
            int minRequiredSize = maxChunkWrite + CRC_LENGTH + blockSize;
            if (configuredSize < minRequiredSize && undersizedBufferWarned.compareAndSet(false, true))
                logger.warn("direct_write_buffer_size ({} bytes) is below the minimum required for SSTable {} " +
                            "(worst-case chunk {} + CRC 4 + blockSize {} = {} bytes); using the minimum. " +
                            "Increase direct_write_buffer_size in cassandra.yaml to silence this warning.",
                            configuredSize, file, maxChunkWrite, blockSize, minRequiredSize);
            int bufferSize = BitUtil.align(Math.max(configuredSize, minRequiredSize), blockSize);

            this.writeBuffer = BufferUtil.allocateDirectAligned(bufferSize, blockSize);
            this.directBufferBytes = bufferSize;
            StorageMetrics.directWriteBufferBytes.inc(bufferSize);
            StorageMetrics.directWriteBuffersAllocated.mark();
        }
        catch (Throwable t)

View on GitHub (pinned to 88fd0f6a0e)

Solutions

  1. Place the data directory on a standard filesystem with a power-of-two block size (typically 4096; ext4/xfs on regular block devices).
  2. Verify the reported block size with `stat -f -c %S` / `stat -c %o`; if it is non-power-of-two, change mount or device.
  3. Disable Direct IO for this environment (leave direct_io disabled) as the deployment target is unsupported for O_DIRECT.

Example fix

// before: fs reports blockSize=3072
throw new IllegalStateException("Filesystem block size must be a power of two for Direct IO. Block size: " + blockSize);
// after: operator moves data dir to ext4 with 4096-byte blocks
// mount -t ext4 /dev/sdX /var/lib/cassandra/data
Defensive patterns

Strategy: validation

Validate before calling

long blockSize = FileUtils.getBlockSize(dataDir);
if (blockSize <= 0 || Long.bitCount(blockSize) != 1) throw new IllegalStateException("Block size not Direct-IO compatible: " + blockSize);

Prevention

When it happens

Trigger: Constructing a DirectCompressedSequentialWriter on a filesystem whose reported logical block size is not a power of two (e.g. some FUSE/9p/network filesystems reporting 3072 or other odd bsize values).

Common situations: Deploying on containers or network mounts (CephFS, some FUSE drivers, odd-over-2KiB block devices) where st_blksize is an unusual value; enabling Direct IO SSTable writes on such a mount.

Understand the failure class

Background: "unsupported platform" / "not supported on this platform" errors: what they mean and how to fix them — this error's family across 47 libraries.

Related errors


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