apache/druid · error · IllegalStateException
Filling row num conversions is supported only with RowCombin
Error message
Filling row num conversions is supported only with RowCombining and Merging iterators
What it means
Thrown in mergeIndexesAndWriteColumns when the row-number conversion buffer is requested but the input indexable's iterator does not implement the RowCombining/RowMerging iterator interfaces needed to support it. Only those iterator types can supply per-row conversion mapping during merge.
Source
Thrown at processing/src/main/java/org/apache/druid/segment/IndexMergerBase.java:834
int maxRowNum = comprisedRows.getMaxCurrentlyCombinedRowNumByOriginalIteratorIndex(originalIteratorIndex);
for (int rowNum = minRowNum; rowNum <= maxRowNum; rowNum++) {
while (conversionBuffer.position() < rowNum) {
conversionBuffer.put(INVALID_ROW);
}
conversionBuffer.put(rowCount);
}
}
} else if (timeAndDimsIterator instanceof MergingRowIterator) {
RowPointer rowPointer = (RowPointer) timeAndDims;
IntBuffer conversionBuffer = rowNumConversions.get(rowPointer.getIndexNum());
int rowNum = rowPointer.getRowNum();
while (conversionBuffer.position() < rowNum) {
conversionBuffer.put(INVALID_ROW);
}
conversionBuffer.put(rowCount);
} else {
throw new IllegalStateException(
"Filling row num conversions is supported only with RowCombining and Merging iterators"
);
}
if ((++rowCount % 500000) == 0) {
log.debug("walked 500,000/%d rows in %,d millis.", rowCount, System.currentTimeMillis() - time);
time = System.currentTimeMillis();
}
}
for (IntBuffer rowNumConversion : rowNumConversions) {
rowNumConversion.rewind();
}
log.debug("completed walk through of %,d rows in %,d millis.", rowCount, System.currentTimeMillis() - startTime);
progress.stopSection(section);
return new IndexMergeResult(
rowNumConversions,
rowCount,
rowCount == 0 ? null : minTime,View on GitHub (pinned to 9b90983fd2)
Solutions
- Do not pass rowNumConversions when merging with plain iterators
- Wrap the input in a merging/combining iterator (e.g. via the QueryableIndex/IncrementalIndex merging paths)
- Use the standard mergeable index implementations (IncrementalIndex/QueryableIndex) so the merger creates combining iterators
Example fix
// before merger.mergeQueryableIndex(indexes, false, aggs, ..., rowNumConversions, ...); // plain iterator lacks combining support // after merger.mergeQueryableIndex(indexes, true /* rollup enables combining iterator */, aggs, ..., rowNumConversions, ...);
Defensive patterns
Strategy: validation
Validate before calling
if (rowNumConversions.length > 0 && !(indexable.getRows() instanceof RowCombiningIterator) && !(indexable.getRows() instanceof RowMergingIterator)) { throw new IllegalStateException("rowNumConversions require a combining/merging iterator"); } Type guard
boolean supportsRowNumConversions(IndexableAdapter a) { return a.getRows() instanceof RowCombiningIterator || a.getRows() instanceof RowMergingIterator; } Try / catch
try { mergeIndexesAndWriteColumns(...); } catch (IllegalStateException e) { if (e.getMessage().contains("RowCombining and Merging iterators")) { /* retry without rowNumConversions or wrap adapter */ } else throw e; } Prevention
- Use standard IncrementalIndex/QueryableIndex inputs to the merger
- Enable rollup so combining iterators are created
- Only set rowNumConversions in code paths known to use merging iterators
When it happens
Trigger: Calling the merge path with rowNumConversions enabled while the segment's iterator is not a RowCombiningIterator/RowMergingIterator (e.g. merging a single non-combining indexable or using an iterator wrapper lacking the interface).
Common situations: Custom segment adapters or pluggable storages feeding the merger; internal use of IndexMerger APIs with rowNumConversions on iterators that don't combine rows (e.g. non-rollup sources).
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- interval %s, bucketId %s mismatched shard specs: %s and %s
- Metric mismatch, index[%d] [%s] != [%s]
- Unknown type[%s]
- Emit called unexpectedly before service start
- unknown event type [%s]
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/4f28803c1c51dbed.
Report an issue: GitHub.