openzipkin/zipkin · error · IllegalArgumentException
endTs <= 0
Error message
endTs <= 0
What it means
Thrown by MySQLSpanStore.getDependencies when the endTs argument is zero or negative. endTs is expected to be an epoch-millisecond timestamp that anchors the dependency-link window. The store validates it up front because the SQL it generates (endTs * 1000 - lookback * 1000) would produce nonsense windows otherwise. A lookback <= 0 is validated the same way on the next line.
Source
Thrown at zipkin-storage/mysql-v1/src/main/java/zipkin2/storage/mysql/v1/MySQLSpanStore.java:106
@Override public Call<List<String>> getServiceNames() {
if (!searchEnabled) return Call.emptyList();
return getServiceNamesCall.clone();
}
@Override public Call<List<String>> getRemoteServiceNames(String serviceName) {
if (serviceName.isEmpty() || !searchEnabled || !schema.hasRemoteServiceName) {
return Call.emptyList();
}
return dataSourceCallFactory.create(new SelectRemoteServiceNames(schema, serviceName));
}
@Override public Call<List<String>> getSpanNames(String serviceName) {
if (serviceName.isEmpty() || !searchEnabled) return Call.emptyList();
return dataSourceCallFactory.create(new SelectSpanNames(schema, serviceName));
}
@Override public Call<List<DependencyLink>> getDependencies(long endTs, long lookback) {
if (endTs <= 0) throw new IllegalArgumentException("endTs <= 0");
if (lookback <= 0) throw new IllegalArgumentException("lookback <= 0");
if (schema.hasPreAggregatedDependencies) {
return dataSourceCallFactory.create(new SelectDependencies(schema, epochDays(endTs, lookback)));
}
return dataSourceCallFactory.create(
new AggregateDependencies(schema, endTs * 1000 - lookback * 1000, endTs * 1000));
}
}
View on GitHub (pinned to 878ce2a1fa)
Solutions
- Pass endTs as epoch milliseconds, e.g. System.currentTimeMillis(), and a positive lookback in millis.
- Validate both arguments at the call site before invoking getDependencies and substitute sane defaults (now, 1 day lookback) when they are unset.
- If wrapping the Zipkin query API in a service, reject requests with endTs <= 0 with a 400 response instead of letting the exception escape.
Example fix
// before long endTs = 0; // never set Call<List<DependencyLink>> call = storage.spanStore().getDependencies(endTs, lookback); // after long endTs = System.currentTimeMillis(); Call<List<DependencyLink>> call = storage.spanStore().getDependencies(endTs, lookback);
Defensive patterns
Strategy: validation
Validate before calling
long endTs = /* from request */; if (endTs <= 0) endTs = System.currentTimeMillis(); if (lookback <= 0) lookback = 86_400_000L; // 1 day Call<List<DependencyLink>> call = storage.spanStore().getDependencies(endTs, lookback);
Try / catch
try { storage.spanStore().getDependencies(endTs, lookback).execute(); } catch (IllegalArgumentException e) { /* map to 400 Bad Request for the caller */ } Prevention
- Treat endTs/lookback as required request parameters and validate them at the API boundary
- Remember units: endTs is epoch millis, not seconds
When it happens
Trigger: Calling MySQLStorage.spanStore().getDependencies(endTs, lookback) with endTs = 0, a negative number, or an uninitialized long. Typically happens when a caller passes seconds instead of millis of passes a default primitive long that was never set.
Common situations: Porting code from another storage backend that accepted 0 as 'now', passing System.currentTimeMillis()/1000 (seconds) where millis is expected, or copying the DependencyLink query from a UI that sends endTs as an optional parameter that defaults to 0.
Related errors
- endTs <= 0
- remoteService={} unsupported due to missing column zipkin_sp
- endTs <= 0
- key == null
- keys == null
AI-assisted analysis of openzipkin/zipkin@878ce2a1fa (2026-08-14).
Data as JSON: /api/errors/3c1d325c63981d32.
Report an issue: GitHub.