{"record":{"id":"39f00a1c5f3aa662","repo":"openzipkin/zipkin","slug":"endts-0-39f00a","errorCode":null,"errorMessage":"endTs <= 0","messagePattern":"endTs <= 0","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":400,"severity":"error","filePath":"zipkin-storage/elasticsearch/src/main/java/zipkin2/elasticsearch/ElasticsearchSpanStore.java","lineNumber":188,"sourceCode":"    long beginMillis = endMillis - namesLookback;\n\n    List<String> indices = indexNameFormatter.formatTypeAndRange(TYPE_SPAN, beginMillis, endMillis);\n    if (indices.isEmpty()) return Call.emptyList();\n\n    // A span name is only valid on a local endpoint, as a span name is defined locally\n    SearchRequest.Filters filters = new SearchRequest.Filters()\n      .addRange(\"timestamp_millis\", beginMillis, endMillis)\n      .addTerm(\"localEndpoint.serviceName\", serviceName.toLowerCase(Locale.ROOT));\n\n    SearchRequest request = SearchRequest.create(indices).filters(filters)\n      .addAggregation(Aggregation.terms(term, Integer.MAX_VALUE));\n\n    return search.newCall(request, BodyConverters.KEYS);\n  }\n\n  @Override\n  public Call<List<DependencyLink>> getDependencies(long endTs, long lookback) {\n    if (endTs <= 0) throw new IllegalArgumentException(\"endTs <= 0\");\n    if (lookback <= 0) throw new IllegalArgumentException(\"lookback <= 0\");\n\n    long beginMillis = Math.max(endTs - lookback, EARLIEST_MS);\n\n    // We just return all dependencies in the days that fall within endTs and lookback as\n    // dependency links themselves don't have timestamps.\n    List<String> indices =\n      indexNameFormatter.formatTypeAndRange(TYPE_DEPENDENCY, beginMillis, endTs);\n    if (indices.isEmpty()) return Call.emptyList();\n\n    return search.newCall(SearchRequest.create(indices), BodyConverters.DEPENDENCY_LINKS);\n  }\n\n  static final class GetSpansByTraceId implements Call.FlatMapper<List<String>, List<Span>> {\n    final SearchCallFactory search;\n    final List<String> indices;\n\n    GetSpansByTraceId(SearchCallFactory search, List<String> indices) {","sourceCodeStart":170,"sourceCodeEnd":206,"githubUrl":"https://github.com/openzipkin/zipkin/blob/878ce2a1fad54ca941d17fdcf2e1d924b148eb1f/zipkin-storage/elasticsearch/src/main/java/zipkin2/elasticsearch/ElasticsearchSpanStore.java#L170-L206","documentation":"ElasticsearchSpanStore.getDependencies(endTs, lookback) returns pre-computed dependency links for the window [endTs - lookback, endTs]. Both arguments must be positive epoch-milliseconds; endTs <= 0 is rejected immediately with IllegalArgumentException because a non-positive end timestamp defines no valid window and would format invalid index names.","triggerScenarios":"Calling getDependencies(0, lookback), getDependencies(-1, ...), or passing seconds instead of epoch millis that underflow to <= 0; also passing an unset primitive long default (0L) from a config object or DTO that was never populated.","commonSituations":"Copy-paste code that assumes endTs defaults to 'now' (it does not — the caller must supply System.currentTimeMillis()); unit tests with dummy zeros; DTOs with primitive long fields left unset.","solutions":["Pass a real epoch-millisecond end timestamp, e.g. System.currentTimeMillis().","Audit the call site for unit bugs (seconds vs millis) and unset long fields.","If endTs is optional in your API, substitute 'now' before calling getDependencies."],"exampleFix":"// before\nstorage.spanStore().getDependencies(0, 86400000L); // IllegalArgumentException: endTs <= 0\n\n// after\nlong endTs = request.endTs() > 0 ? request.endTs() : System.currentTimeMillis();\nstorage.spanStore().getDependencies(endTs, 86400000L);","handlingStrategy":"validation","validationCode":"long endTs = (request.endTs() > 0) ? request.endTs() : System.currentTimeMillis();\nlong lookback = (request.lookback() > 0) ? request.lookback() : 86400000L;\nif (endTs <= 0 || lookback <= 0) {\n  throw new IllegalArgumentException(\"endTs and lookback must be positive epoch millis\");\n}\nCall<List<DependencyLink>> links = storage.spanStore().getDependencies(endTs, lookback);","typeGuard":"static boolean isValidDependencyWindow(long endTs, long lookback) {\n  return endTs > 0 && lookback > 0; // both must be positive epoch-millis\n}","tryCatchPattern":null,"preventionTips":["Never pass primitive-default 0L: default unset endTs to System.currentTimeMillis().","Keep timestamps in epoch milliseconds everywhere; check for accidental seconds at the boundary.","Validate window arguments in your API layer with a 400 response before calling getDependencies."],"tags":["elasticsearch","dependencies","validation","epoch-millis","storage"],"backgroundTag":null,"analyzedSha":"878ce2a1fad54ca941d17fdcf2e1d924b148eb1f","analyzedAt":"2026-08-14T15:17:09.895Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}