{"record":{"id":"87aa88fed4112de4","repo":"apache/druid","slug":"row-compares-higher-than-mark-out-of-order-input","errorCode":null,"errorMessage":"Row compares higher than mark; out-of-order input?","messagePattern":"Row compares higher than mark; out-of-order input\\?","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"multi-stage-query/src/main/java/org/apache/druid/msq/querykit/common/SortMergeJoinFrameProcessor.java","lineNumber":846,"sourceCode":"     * Whether the provided frame and row compares equally to the mark row. The provided row must be at, or after,\n     * the mark row.\n     */\n    private boolean isSameKeyAsMark(final FrameHolder holder, final int row)\n    {\n      if (markFrame < 0) {\n        throw new ISE(\"No marked frame\");\n      }\n      if (row < 0 || row >= holder.frame.numRows()) {\n        throw new ISE(\"Row [%d] out of bounds\", row);\n      }\n\n      final FrameHolder markHolder = holders.get(markFrame);\n      final int cmp = markHolder.comparisonWidget.compare(markRow, holder.comparisonWidget, row);\n\n      if (cmp > 0) {\n        // The provided row is at, or after, the marked row.\n        // Therefore, cmp > 0 may indicate that input was provided out of order.\n        throw new ISE(\"Row compares higher than mark; out-of-order input?\");\n      }\n\n      return cmp == 0;\n    }\n  }\n\n  /**\n   * Selector for joined rows. This is used as an input to {@link #frameWriter}.\n   */\n  private class JoinColumnSelectorFactory implements ColumnSelectorFactory\n  {\n    /**\n     * Current key comparison between left- and right-hand side.\n     */\n    private int cmp;\n\n    /**\n     * Whether there is a match between the left- and right-hand side. Not equivalent to {@code cmp == 0} in","sourceCodeStart":828,"sourceCodeEnd":864,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/multi-stage-query/src/main/java/org/apache/druid/msq/querykit/common/SortMergeJoinFrameProcessor.java#L828-L864","documentation":"During sort-merge join key comparison, isSameKeyAsMark expects each incoming row to be at or after the marked row in sort order. When the comparison says the current row sorts before the marked row (cmp > 0), an IllegalStateException('Row compares higher than mark; out-of-order input?') is thrown because the join's correctness depends on inputs sorted by the join key.","triggerScenarios":"Input frames arriving out of order by the join key — e.g. the upstream sorting stage produced/dispatched rows non-monotonically, or a custom/extended stage violated ordering assumptions; called from hasCompleteSetForMark and isCurrentSameKeyAsMark.","commonSituations":"Engine bugs in key ordering or partitioning; external data sources or modified pipelines feeding unsorted data into a stage that assumes sorted input; concurrent frame mutation in custom query-kit extensions.","solutions":["Verify inputs are genuinely sorted by the join key before the merge stage (do not bypass MSQ's sort steps)","Retry; if reproducible, file a Druid bug with the query and stack trace","Avoid custom stage substitutions/extensions that alter frame ordering","Ensure both join sides use identical key ordering/columns in ORDER/cluster settings"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  runMsqQuery(query);\n} catch (IllegalStateException | MSQException e) {\n  if (e.getMessage() != null && e.getMessage().contains(\"out-of-order input\")) {\n    // verify upstream ordering; retry or report engine bug with query\n  }\n}","preventionTips":["Never bypass MSQ's sort stages feeding a sort-merge join","Keep join key ordering identical on both inputs","Avoid custom extensions that reorder frames"],"tags":["msq","join","sorting","invariant"],"backgroundTag":"internal-invariant-violation","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}