openzipkin/zipkin · error · IllegalArgumentException
limit <= 0
Error message
limit <= 0
What it means
Thrown by QueryRequest.Builder.build() in zipkin2.storage when the configured limit is zero or negative. The limit controls how many traces the storage backend returns per query, and Zipkin requires at least one result. This is a fail-fast guard so invalid queries never reach a storage component.
Source
Thrown at zipkin/src/main/java/zipkin2/storage/QueryRequest.java:251
/** Sets {@link QueryRequest#limit()} */
public Builder limit(int limit) {
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,View on GitHub (pinned to 878ce2a1fa)
Solutions
- Set a positive limit, e.g. .limit(10) (the conventional Zipkin default) before build()
- Validate/sanitize any externally supplied limit: limit = Math.max(1, requestedLimit)
- If the value comes from config, check the property name/spelling and its resolved value at startup
Example fix
// before
QueryRequest request = QueryRequest.newBuilder()
.endTs(endTs)
.limit(0) // throws "limit <= 0"
.build();
// after
QueryRequest request = QueryRequest.newBuilder()
.endTs(endTs)
.limit(10)
.build(); Defensive patterns
Strategy: validation
Validate before calling
// before building the request
if (requestedLimit == null || requestedLimit <= 0) {
throw new IllegalArgumentException("limit must be a positive integer, got: " + requestedLimit);
}
QueryRequest request = QueryRequest.newBuilder().endTs(endTs).limit(requestedLimit).build(); Try / catch
try {
return QueryRequest.newBuilder().endTs(endTs).limit(limit).build();
} catch (IllegalArgumentException e) {
// treat as caller input error: log and rethrow as 400-style error, do not retry
throw new BadRequestException("Invalid trace query: " + e.getMessage(), e);
} Prevention
- Centralize QueryRequest construction in one factory method that clamps limit to a sane range (e.g. 1..1000)
- Validate user-supplied query parameters at the API boundary, not inside storage code
- Fail fast at startup if limit comes from config: assert it is >= 1
When it happens
Trigger: Calling QueryRequest.newBuilder().limit(0) (or a negative value) followed by build(); programmatically computing limit from a page-size variable that evaluates to 0 (e.g. empty config, integer underflow); passing a client-supplied ?limit=0 through to the builder without validating it first.
Common situations: Reading limit from application config/properties where the key is missing and defaults to 0 or unparses to 0; UI pagination code that passes 0 for 'no limit'; porting older code that assumed the server would silently clamp the value.
Related errors
- concurrency < 1
- loggingClass == null
- rate should be between 0 and 1: was {}
- concurrency < 1
- clientProps is empty
AI-assisted analysis of openzipkin/zipkin@878ce2a1fa (2026-08-14).
Data as JSON: /api/errors/c13b58938df26755.
Report an issue: GitHub.