openzipkin/zipkin · error · IllegalArgumentException
minDuration <= 0
Error message
minDuration <= 0
What it means
Thrown by QueryRequest.Builder.build() when minDuration is set to zero or a negative value. minDuration filters traces by span duration in microseconds, and a non-positive duration is meaningless as a filter. Zipkin rejects it at build time rather than returning wrong results.
Source
Thrown at zipkin/src/main/java/zipkin2/storage/QueryRequest.java:254
this.limit = limit;
return this;
}
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
- Pass a positive duration in microseconds, e.g. .minDuration(100000) for 100ms
- If minDuration is optional, leave it unset (null) instead of setting it to 0
- Audit unit conversions feeding the value (ms to micros is *1000, nanos to micros is /1000)
Example fix
// before builder.minDuration(durationMs / 1000); // integer division may yield 0 // after builder.minDuration(durationMs * 1000); // milliseconds -> microseconds
Defensive patterns
Strategy: validation
Validate before calling
// duration is in microseconds; must be positive if present
if (minDuration != null && minDuration <= 0) {
throw new IllegalArgumentException("minDuration must be positive microseconds, got: " + minDuration);
}
QueryRequest.Builder b = QueryRequest.newBuilder().endTs(endTs).limit(10);
if (minDuration != null) b.minDuration(minDuration); Try / catch
try {
builder.minDuration(minDurationMicros);
} catch (IllegalArgumentException e) {
// input bug, never retry: surface the message to the caller/API client
throw new BadRequestException(e.getMessage(), e);
} Prevention
- Name variables with their unit (minDurationMicros) to prevent ms/micros mix-ups
- Treat a blank/absent duration filter as null, not 0
- Write one conversion helper for ms->micros and use it everywhere
When it happens
Trigger: Calling .minDuration(0L) or .minDuration(-5L) on the builder; converting a user-supplied duration in the wrong unit (e.g. passing 0 nanoseconds after integer division, or a value already divided to 0); passing a duration string that failed to parse and defaulted to 0.
Common situations: Unit confusion between milliseconds, microseconds, and nanoseconds leading to a computed 0; a 'min duration' UI field left blank and coerced to 0; copying example code that used 0 as a placeholder.
Related errors
- maxDuration < minDuration
- 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/7e9086b1082c3f74.
Report an issue: GitHub.