openzipkin/zipkin · error · NullPointerException

key == null

Error message

key == null

What it means

ElasticsearchAutocompleteTags.getValues(key) fetches distinct values for an autocomplete tag key within the names lookback window. The API contract requires a non-null, non-empty key; null fails fast with NullPointerException('key == null') before any query is built. This is a programmer-error guard, not an environmental failure.

Source

Thrown at zipkin-storage/elasticsearch/src/main/java/zipkin2/elasticsearch/ElasticsearchAutocompleteTags.java:39

  final SearchCallFactory search;
  final int namesLookback;
  final Call<List<String>> keysCall;

  ElasticsearchAutocompleteTags(ElasticsearchStorage es) {
    this.search = new SearchCallFactory(es.http());
    this.indexNameFormatter = es.indexNameFormatter();
    this.enabled = es.searchEnabled() && !es.autocompleteKeys().isEmpty();
    this.namesLookback = es.namesLookback();
    this.keysCall = Call.create(es.autocompleteKeys());
  }

  @Override public Call<List<String>> getKeys() {
    if (!enabled) return Call.emptyList();
    return keysCall.clone();
  }

  @Override public Call<List<String>> getValues(String key) {
    if (key == null) throw new NullPointerException("key == null");
    if (key.isEmpty()) throw new IllegalArgumentException("key was empty");
    if (!enabled) return Call.emptyList();

    long endMillis = System.currentTimeMillis();
    long beginMillis = endMillis - namesLookback;
    List<String> indices =
      indexNameFormatter.formatTypeAndRange(TYPE_AUTOCOMPLETE, beginMillis, endMillis);

    if (indices.isEmpty()) return Call.emptyList();

    SearchRequest.Filters filters =
      new SearchRequest.Filters().addTerm("tagKey", key);

    SearchRequest request = SearchRequest.create(indices)
      .filters(filters)
      .addAggregation(Aggregation.terms("tagValue", Integer.MAX_VALUE));
    return search.newCall(request, BodyConverters.KEYS);
  }

View on GitHub (pinned to 878ce2a1fa)

Solutions

  1. Fix the caller to pass a non-null key; trace where the null originates (often an unchecked request parameter).
  2. Validate at the boundary: reject or skip requests with a missing key before reaching storage.
  3. If the key is optional in your API, return an empty list instead of calling getValues.

Example fix

// before
String key = request.getParameter("key"); // may be null
Call<List<String>> values = storage.autocompleteTags().getValues(key); // NPE

// after
String key = request.getParameter("key");
if (key == null || key.isEmpty()) return Collections.emptyList();
Call<List<String>> values = storage.autocompleteTags().getValues(key);
Defensive patterns

Strategy: validation

Validate before calling

if (key == null || key.isEmpty()) {
  return Collections.emptyList(); // or reject the request with 400
}

Type guard

static boolean isQueryableKey(String key) {
  return key != null && !key.isEmpty();
}

Prevention

When it happens

Trigger: Calling autocompleteTags().getValues(null) on ElasticsearchStorage, typically because a caller forwarded an unvalidated request parameter (e.g. a missing ?key= query param from an HTTP API) straight into getValues.

Common situations: Building a custom UI or REST facade over the SpanStore API where the key arrives from user input and optional parameters are not filtered; refactoring that introduces a null path; tests that pass null by accident.

Related errors


AI-assisted analysis of openzipkin/zipkin@878ce2a1fa (2026-08-14). Data as JSON: /api/errors/1357c6fefc107f3a. Report an issue: GitHub.