{"record":{"id":"4d9f1b3978cbdeac","repo":"apache/cassandra","slug":"filesystem-block-size-must-be-a-power-of-two-for-d","errorCode":null,"errorMessage":"Filesystem block size must be a power of two for Direct IO. Block size: %d","messagePattern":"Filesystem block size must be a power of two for Direct IO\\. Block size: (.+?)","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/io/compress/DirectCompressedSequentialWriter.java","lineNumber":115,"sourceCode":"                                            @Nullable File digestFile,\n                                            SequentialWriterOption option,\n                                            CompressionParams parameters,\n                                            MetadataCollector sstableMetadataCollector,\n                                            @Nullable CompressionDictionaryManager compressionDictionaryManager)\n    {\n        super(file, offsetsFile, digestFile, option, parameters, sstableMetadataCollector, compressionDictionaryManager, ExtendedOpenOption.DIRECT);\n\n        // super() opened the O_DIRECT FileChannel and allocated parent buffers; if anything below throws\n        // the caller never gets a reference to clean them up, so abort the txn proxy ourselves.\n        try\n        {\n            this.blockSize = FileUtils.getBlockSize(file.parent());\n            if (blockSize <= 0)\n                throw new IllegalStateException(\"Unable to determine filesystem block size for Direct IO. \" +\n                                                \"Block size: \" + blockSize);\n\n            if (!BitUtil.isPowerOfTwo(blockSize))\n                throw new IllegalStateException(\"Filesystem block size must be a power of two for Direct IO. \" +\n                                                \"Block size: \" + blockSize);\n\n            int configuredSize = DatabaseDescriptor.getDirectWriteBufferSize().toBytes();\n            int maxChunkWrite = parameters.getSstableCompressor().initialCompressedBufferLength(parameters.chunkLength());\n            int minRequiredSize = maxChunkWrite + CRC_LENGTH + blockSize;\n            if (configuredSize < minRequiredSize && undersizedBufferWarned.compareAndSet(false, true))\n                logger.warn(\"direct_write_buffer_size ({} bytes) is below the minimum required for SSTable {} \" +\n                            \"(worst-case chunk {} + CRC 4 + blockSize {} = {} bytes); using the minimum. \" +\n                            \"Increase direct_write_buffer_size in cassandra.yaml to silence this warning.\",\n                            configuredSize, file, maxChunkWrite, blockSize, minRequiredSize);\n            int bufferSize = BitUtil.align(Math.max(configuredSize, minRequiredSize), blockSize);\n\n            this.writeBuffer = BufferUtil.allocateDirectAligned(bufferSize, blockSize);\n            this.directBufferBytes = bufferSize;\n            StorageMetrics.directWriteBufferBytes.inc(bufferSize);\n            StorageMetrics.directWriteBuffersAllocated.mark();\n        }\n        catch (Throwable t)","sourceCodeStart":97,"sourceCodeEnd":133,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/io/compress/DirectCompressedSequentialWriter.java#L97-L133","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Place the data directory on a standard filesystem with a power-of-two block size (typically 4096; ext4/xfs on regular block devices).","Verify the reported block size with `stat -f -c %S` / `stat -c %o`; if it is non-power-of-two, change mount or device.","Disable Direct IO for this environment (leave direct_io disabled) as the deployment target is unsupported for O_DIRECT."],"exampleFix":"// before: fs reports blockSize=3072\nthrow new IllegalStateException(\"Filesystem block size must be a power of two for Direct IO. Block size: \" + blockSize);\n// after: operator moves data dir to ext4 with 4096-byte blocks\n// mount -t ext4 /dev/sdX /var/lib/cassandra/data","handlingStrategy":"validation","validationCode":"long blockSize = FileUtils.getBlockSize(dataDir);\nif (blockSize <= 0 || Long.bitCount(blockSize) != 1) throw new IllegalStateException(\"Block size not Direct-IO compatible: \" + blockSize);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Verify the mount's logical block size is a power of two (usually 4096) before enabling direct-io.","Avoid FUSE/network filesystems for Direct IO data directories.","Document storage requirements for Direct IO in your deployment runbook."],"tags":["direct-io","filesystem","block-size","alignment"],"backgroundTag":"unsupported-platform","analyzedSha":"88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1","analyzedAt":"2026-09-10T07:29:22.284Z","contentChangedAt":"2026-09-10T07:29:22.284Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}