apache/cassandra · warning

direct_write_buffer_size

Error message

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.

What it means

DirectCompressedSequentialWriter validates that the configured direct_write_buffer_size can hold the worst-case compressed chunk plus CRC bytes and blockSize alignment. When it is too small, the writer clamps the buffer up to the computed minimum and logs this warning once (guarded by an AtomicBoolean CAS) telling the operator to raise the yaml setting.

Solutions

  1. Increase direct_write_buffer_size in cassandra.yaml to at least the reported minRequiredSize and restart
  2. Reduce chunk_length_in_kb in the table's compression options so the worst-case chunk fits the current buffer
  3. Ignore the warning if the automatic clamping is acceptable — writes still work with the minimum-sized buffer

Example fix

// before (cassandra.yaml)
direct_write_buffer_size: 128KiB
// after — must exceed worst-case chunk + CRC(4) + blockSize
direct_write_buffer_size: 1MiB
Defensive patterns

Strategy: validation

Validate before calling

// Pre-check before enabling direct-IO compressed writes:
int min = compressor.initialCompressedBufferLength(chunkLength) + 4 + blockSize;
if (DatabaseDescriptor.getDirectWriteBufferSize().toBytes() < min)
    throw new IllegalStateException("Increase direct_write_buffer_size to >= " + min);

Prevention

When it happens

Trigger: DatabaseDescriptor.getDirectWriteBufferSize() < initialCompressedBufferLength(chunkLength) + 4 (CRC) + blockSize for the sstable's compressor; occurs when creating a direct-IO compressed sequential writer for a memtable flush/streaming write.

Common situations: Operators lowered direct_write_buffer_size in cassandra.yaml to save memory; large chunk_length_in_kb with a compressor that can inflate data (worst-case size exceeds input); high blockSize making min required size larger than expected.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


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

Appendix: source

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

        // 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)
        {
            Throwable merged = t;
            try { merged = abort(t); }
            catch (Throwable t2) { t.addSuppressed(t2); }
            Throwables.maybeFail(merged);
            // Unreachable: maybeFail(non-null) always throws. Present for definite-assignment of `blockSize`.
            throw new AssertionError("Throwables.maybeFail should have thrown", merged);

View on GitHub (pinned to 88fd0f6a0e)