apache/druid · error · IllegalStateException

Cannot apply limit[%d] with offset[%d] due to overflow

Error message

Cannot apply limit[%d] with offset[%d] due to overflow

What it means

DefaultLimitSpec.withOffsetToLimit rewrites a limit spec with an offset into an equivalent spec with offset 0 and limit = limit + offset. If that sum would exceed Integer.MAX_VALUE, the rewrite would overflow int arithmetic, so it deliberately throws an IllegalStateException instead of silently wrapping.

Source

Thrown at processing/src/main/java/org/apache/druid/query/groupby/orderby/DefaultLimitSpec.java:323

  }

  /**
   * Returns a new DefaultLimitSpec identical to this one except for one difference: an offset parameter, if any, will
   * be removed and added to the limit. This is designed for passing down queries to lower levels of the stack. Only
   * the highest level should apply the offset parameter, and any pushed-down limits must be increased to accommodate
   * the offset.
   */
  public DefaultLimitSpec withOffsetToLimit()
  {
    if (isOffset()) {
      final int newLimit;

      if (limit == Integer.MAX_VALUE) {
        // Unlimited stays unlimited.
        newLimit = Integer.MAX_VALUE;
      } else if (limit > Integer.MAX_VALUE - offset) {
        // Handle overflow as best we can.
        throw new ISE("Cannot apply limit[%d] with offset[%d] due to overflow", limit, offset);
      } else {
        newLimit = limit + offset;
      }

      return new DefaultLimitSpec(columns, 0, newLimit);
    } else {
      return this;
    }
  }

  private Ordering<ResultRow> makeComparator(
      RowSignature rowSignature,
      boolean hasTimestamp,
      List<DimensionSpec> dimensions,
      List<AggregatorFactory> aggs,
      List<PostAggregator> postAggs,
      boolean sortByDimsFirst
  )

View on GitHub (pinned to 9b90983fd2)

Solutions

  1. Use a smaller limit so limit + offset stays within Integer.MAX_VALUE.
  2. Model 'unlimited' as limit = Integer.MAX_VALUE with offset 0 rather than adding offsets to MAX_VALUE.
  3. Guard the offset application in caller code: only call withOffsetToLimit when (long)limit + offset <= Integer.MAX_VALUE.

Example fix

// before
new DefaultLimitSpec(columns, offset, Integer.MAX_VALUE).withOffsetToLimit(offset)
// after
int limit = limitSpec.getLimit() == Integer.MAX_VALUE ? Integer.MAX_VALUE : limitSpec.getLimit() - offset;
Defensive patterns

Strategy: validation

Validate before calling

if (limit != Integer.MAX_VALUE && (long) limit + offset > Integer.MAX_VALUE) {
  throw new IllegalArgumentException("limit+offset overflows int");
}

Try / catch

try {
  return spec.withOffsetToLimit(offset);
} catch (IllegalStateException e) {
  if (e.getMessage() != null && e.getMessage().contains("due to overflow")) {
    return new DefaultLimitSpec(spec.getColumns(), 0, Integer.MAX_VALUE);
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling withOffsetToLimit on a DefaultLimitSpec whose combined limit + offset exceeds Integer.MAX_VALUE (e.g. limit near Integer.MAX_VALUE plus a positive offset); invoked during query planning when converting offsets to limits.

Common situations: Users setting huge limits like 2147483647 plus an offset for 'all rows' semantics; programmatic limit construction with sentinel MAX_VALUE values; pagination helpers that add offsets to unbounded limits.

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/druid@9b90983fd2 (2026-09-07). Data as JSON: /api/errors/a1f8f402618328ed. Report an issue: GitHub.