apache/druid · error · IllegalStateException
Row [%d] out of bounds
Error message
Row [%d] out of bounds
What it means
isSameKeyAsMark validates that the row being compared lies inside the frame's row range. If markFrame is unset or the row index is negative or >= holder.frame.numRows(), an IllegalStateException('Row [%d] out of bounds') is thrown, indicating the merge-join logic attempted to compare a row that does not exist — an internal invariant breach rather than a data or user error.
Source
Thrown at multi-stage-query/src/main/java/org/apache/druid/msq/querykit/common/SortMergeJoinFrameProcessor.java:837
public void clear()
{
holders.clear();
markFrame = -1;
markRow = -1;
currentFrame = -1;
}
/**
* Whether the provided frame and row compares equally to the mark row. The provided row must be at, or after,
* the mark row.
*/
private boolean isSameKeyAsMark(final FrameHolder holder, final int row)
{
if (markFrame < 0) {
throw new ISE("No marked frame");
}
if (row < 0 || row >= holder.frame.numRows()) {
throw new ISE("Row [%d] out of bounds", row);
}
final FrameHolder markHolder = holders.get(markFrame);
final int cmp = markHolder.comparisonWidget.compare(markRow, holder.comparisonWidget, row);
if (cmp > 0) {
// The provided row is at, or after, the marked row.
// Therefore, cmp > 0 may indicate that input was provided out of order.
throw new ISE("Row compares higher than mark; out-of-order input?");
}
return cmp == 0;
}
}
/**
* Selector for joined rows. This is used as an input to {@link #frameWriter}.
*/View on GitHub (pinned to 9b90983fd2)
Solutions
- Retry the query; if reproducible, file a Druid bug including the query and stack trace
- Adjust frame/row batch sizing context parameters as a workaround to shift frame boundaries
- Reduce join input sizes (filter, pre-aggregate) to avoid the failing boundary condition
- Check for a newer Druid version with fixes to SortMergeJoinFrameProcessor
Defensive patterns
Strategy: retry
Try / catch
try {
runMsqQuery(query);
} catch (IllegalStateException | MSQException e) {
if (e.getMessage() != null && e.getMessage().contains("out of bounds")) {
// engine bug: retry once, then collect query/trace and report to Druid
}
} Prevention
- Keep Druid current; this class of bug is fixed in engine releases
- Avoid custom stage extensions that mutate frame bookkeeping
- Capture full stack traces for bug reports
When it happens
Trigger: Internal: during hasCompleteSetForMark or isCurrentSameKeyAsMark, the processor passes a row index outside the current frame holder (cursor bookkeeping desync, e.g. after a frame flush or boundary miscount).
Common situations: Rarely user-caused; surfaces as an engine bug in sort-merge join cursor management, potentially reproducible with particular frame-boundary sizes and join key orderings; report to Druid with the query.
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
- Row compares higher than mark; out-of-order input?
- Cannot handle inputSpec of class [%s]
- Lookup[%s] has multiple segments; cannot read
- Stage[%d] output partitions not available
- BroadcastTablesTooLarge
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/15a386ebf1dd3fdd.
Report an issue: GitHub.