apache/druid · error · IllegalArgumentException (IAE)
'skip' must be greater than zero
Error message
'skip' must be greater than zero
What it means
ScanQueryOffsetSequence wraps a base scan sequence to skip the first N result rows (query offset). A skip value below 1 is meaningless (offset must be at least 1 to have an effect), so the constructor throws IAE immediately.
Source
Thrown at processing/src/main/java/org/apache/druid/query/scan/ScanQueryOffsetSequence.java:48
import java.util.List;
import java.util.stream.Collectors;
/**
* A Sequence that wraps the results of a ScanQuery and skips a given number of rows. It is used to implement
* the "offset" feature.
*/
public class ScanQueryOffsetSequence extends YieldingSequenceBase<ScanResultValue>
{
private final Sequence<ScanResultValue> baseSequence;
private final long skip;
public ScanQueryOffsetSequence(Sequence<ScanResultValue> baseSequence, long skip)
{
this.baseSequence = baseSequence;
this.skip = skip;
if (skip < 1) {
throw new IAE("'skip' must be greater than zero");
}
}
@Override
public <OutType> Yielder<OutType> toYielder(
final OutType initValue,
final YieldingAccumulator<OutType, ScanResultValue> accumulator
)
{
final SkippingYieldingAccumulator<OutType> skippingAccumulator = new SkippingYieldingAccumulator<>(accumulator);
return wrapYielder(baseSequence.toYielder(initValue, skippingAccumulator), skippingAccumulator);
}
private <OutType> Yielder<OutType> wrapYielder(
final Yielder<OutType> yielder,
final SkippingYieldingAccumulator<OutType> accumulator
)
{View on GitHub (pinned to 9b90983fd2)
Solutions
- Only wrap with ScanQueryOffsetSequence when query.getScanRowsOffset() >= 1
- Fix client-supplied offset values to be at least 1 (or omit offset)
- Guard construction: if (offset > 0) apply offset sequence, else use base sequence
Example fix
// before Sequence<ScanResultValue> seq = new ScanQueryOffsetSequence(base, query.getScanRowsOffset()); // offset may be 0 // after final long offset = query.getScanRowsOffset(); Sequence<ScanResultValue> seq = offset >= 1 ? new ScanQueryOffsetSequence(base, offset) : base;
Defensive patterns
Strategy: validation
Validate before calling
long offset = query.getScanRowsOffset();
if (offset < 1) { /* do not construct ScanQueryOffsetSequence */ } Type guard
boolean offsetApplicable(ScanQuery q) { return q.getScanRowsOffset() >= 1; } Try / catch
try {
seq = new ScanQueryOffsetSequence(base, skip);
} catch (IllegalArgumentException e) {
seq = base; // skip<=0 means no offset needed
} Prevention
- Only apply offset sequencing when offset > 0
- Sanitize client-provided offset values to be positive integers
- Document that offset starts at 1 when used
When it happens
Trigger: Constructing ScanQueryOffsetSequence with skip = 0 or negative, typically from a ScanQuery whose getScanRowsOffset() is 0 or negative (e.g. context 'offset':0 applied via mergeResults).
Common situations: Programmatic query building where offset defaults to 0 and the offset sequence is applied unconditionally; manual API misuse; clients sending negative offset values in query context.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Cannot apply limit[%d] with offset[%d] due to overflow
- Emit called unexpectedly before service start
- Got an exception while parsing file [%s]
- Unable to copy key [%s] to file [%s]
- startFrame[%,d] < 0
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/6ade58f9c7b0de29.
Report an issue: GitHub.