apache/cassandra · error · RuntimeException
Last written key %s >= current key %s, writing into %s
Error message
Last written key %s >= current key %s, writing into %s
What it means
SortedTableWriter.verifyPartition enforces the SSTable invariant that partitions must be written in strictly increasing decorated-key order. If the key about to be appended compares <= the last written key, it throws, because BigFormat requires sorted input and would otherwise produce an unreadable/invalid SSTable.
Source
Thrown at src/java/org/apache/cassandra/io/sstable/format/SortedTableWriter.java:198
}
catch (IOException e)
{
throw new FSWriteError(e, getFilename());
}
}
private boolean verifyPartition(DecoratedKey key)
{
assert key != null : "Keys must not be null"; // empty keys ARE allowed b/c of indexed column values
if (key.getKey().remaining() > FBUtilities.MAX_UNSIGNED_SHORT)
{
logger.error("Key size {} exceeds maximum of {}, skipping row", key.getKey().remaining(), FBUtilities.MAX_UNSIGNED_SHORT);
return false;
}
if (lastWrittenKey != null && lastWrittenKey.compareTo(key) >= 0)
throw new RuntimeException(String.format("Last written key %s >= current key %s, writing into %s", lastWrittenKey, key, getFilename()));
return true;
}
private void startPartition(DecoratedKey key, DeletionTime partitionLevelDeletion) throws IOException
{
partitionWriter.start(key, partitionLevelDeletion);
metadataCollector.updatePartitionDeletion(partitionLevelDeletion);
onStartPartition(key);
}
private void addStaticRow(DecoratedKey key, Row row) throws IOException
{
guardCollectionSize(key, row);
partitionWriter.addStaticRow(row);
if (!row.isEmpty())View on GitHub (pinned to 88fd0f6a0e)
Solutions
- Sort partitions by DecoratedKey before appending (DecoratedKey.compareTo, which orders by token then key bytes).
- For bulk loads, feed the writer from an ordered source or use tools that sort internally (e.g. BulkLoader/CQLSSTableWriter usage guidelines).
- If writing an SSTable from unsorted data, buffer and externally merge-sort by token first.
- Check custom compaction/streaming code for iteration order assumptions.
Example fix
// before: appending keys in arbitrary order
for (UnfilteredRowIterator part : unsortedPartitions)
writer.append(part);
// after: sort by decorated key first
unsortedPartitions.sort(Comparator.comparing(p ->
partitioner.decorateKey(StorageEngine.getPartitionKey(p))));
for (UnfilteredRowIterator part : unsortedPartitions)
writer.append(part); Defensive patterns
Strategy: validation
Validate before calling
// Java: assert incoming partitions are sorted before writing
DecoratedKey prev = null;
for (UnfilteredRowIterator part : partitions) {
DecoratedKey k = decorateKey(part.partitionKey());
if (prev != null && prev.compareTo(k) >= 0)
throw new IllegalStateException("Unsorted partitions at " + k);
prev = k;
} Try / catch
try {
writer.append(partition);
} catch (RuntimeException e) {
if (e.getMessage().contains("Last written key"))
logger.error("Bulk loader emitted unsorted keys — re-sort source data", e);
throw e;
} Prevention
- Always sort by DecoratedKey (token then bytes) before writing SSTables
- Use CQLSSTableWriter/BulkLoader rather than hand-rolled writers
- Unit-test custom streaming/compaction code for key order
When it happens
Trigger: Calling sstableWriter.append(partition, ...) with keys not sorted by DecoratedKey — typically a compaction/scrub/rebuild iterating sources out of order, a custom streaming or bulk-loader writing unsorted partitions, or merging sources that yield keys out of order.
Common situations: Custom bulk load tools (sstable writer APIs) feeding unsorted data; bugs in custom compaction strategies or external stream receivers; repairing data with mismatched sort order after reading from an unordered source.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- No holder claimed
- SSTable format name in %s cannot be null
- SSTable format name for %s must be non-empty, lower-case let
- Multiple sstable format implementations with the same name %
- Configuration contains options of unknown sstable formats: %
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/bba71811e1531a7e.
Report an issue: GitHub.