openzipkin/zipkin · error · IllegalArgumentException
maxDuration < minDuration
Error message
maxDuration < minDuration
What it means
Thrown by QueryRequest.Builder.build() when both minDuration and maxDuration are set but maxDuration is smaller than minDuration. The pair defines a duration window in microseconds; an inverted window is logically empty, so Zipkin rejects it eagerly as a caller bug.
Source
Thrown at zipkin/src/main/java/zipkin2/storage/QueryRequest.java:256
}
public QueryRequest build() {
// coerce service and span names to lowercase
if (serviceName != null) serviceName = serviceName.toLowerCase(Locale.ROOT);
if (remoteServiceName != null) remoteServiceName = remoteServiceName.toLowerCase(Locale.ROOT);
if (spanName != null) spanName = spanName.toLowerCase(Locale.ROOT);
if ("".equals(serviceName)) serviceName = null;
if ("".equals(remoteServiceName)) remoteServiceName = null;
if ("".equals(spanName) || "all".equals(spanName)) spanName = null;
if (endTs <= 0) throw new IllegalArgumentException("endTs <= 0");
if (limit <= 0) throw new IllegalArgumentException("limit <= 0");
if (lookback <= 0) throw new IllegalArgumentException("lookback <= 0");
if (minDuration != null) {
if (minDuration <= 0) throw new IllegalArgumentException("minDuration <= 0");
if (maxDuration != null && maxDuration < minDuration) {
throw new IllegalArgumentException("maxDuration < minDuration");
}
} else if (maxDuration != null) {
throw new IllegalArgumentException("maxDuration is only valid with minDuration");
}
return new QueryRequest(
serviceName,
remoteServiceName,
spanName,
annotationQuery,
minDuration,
maxDuration,
endTs,
lookback,
limit
);
}
View on GitHub (pinned to 878ce2a1fa)
Solutions
- Ensure maxDuration >= minDuration, both in microseconds, before calling build()
- If the intent is a window, compute max explicitly: maxDuration = minDuration + windowMicros
- Add a UI/service-side validation that rejects or swaps inverted min/max pairs before they reach the builder
Example fix
// before builder.minDuration(maxDuration).maxDuration(minDuration); // swapped // after builder.minDuration(minDuration).maxDuration(maxDuration);
Defensive patterns
Strategy: validation
Validate before calling
if (minDuration != null && maxDuration != null && maxDuration < minDuration) {
throw new IllegalArgumentException(
"maxDuration (" + maxDuration + ") must be >= minDuration (" + minDuration + ")");
}
QueryRequest.Builder b = QueryRequest.newBuilder().endTs(endTs).limit(10)
.minDuration(minDuration);
if (maxDuration != null) b.maxDuration(maxDuration); Try / catch
try {
builder.minDuration(min).maxDuration(max).build();
} catch (IllegalArgumentException e) {
// logical input error: report to user, do not retry
throw new BadRequestException(e.getMessage(), e);
} Prevention
- Validate min<=max in UI/service code before the value reaches Zipkin
- Derive maxDuration from minDuration plus a positive window instead of independent inputs
- Add a unit test covering the inverted-range case
When it happens
Trigger: Calling .minDuration(50000).maxDuration(10000) on the builder; swapping the two values when wiring UI fields; computing maxDuration from a delta (e.g. minDuration + range) where the delta is negative or the subtraction underflows.
Common situations: Two form fields ('min'/'max duration') entered in the wrong order by a user and passed through unvalidated; refactoring that renames variables and accidentally swaps the arguments; off-by-unit bugs that shrink maxDuration below minDuration.
Related errors
- minDuration <= 0
- maxDuration is only valid with minDuration
- concurrency < 1
- rate should be between 0 and 1: was {}
- limit <= 0
AI-assisted analysis of openzipkin/zipkin@878ce2a1fa (2026-08-14).
Data as JSON: /api/errors/f5ae32ff694c0c63.
Report an issue: GitHub.