openzipkin/zipkin · error · NullPointerException

key == null

Error message

key == null

What it means

MySQLAutocompleteTags.getValues(key) runs a SelectAutocompleteValues query against the zipkin_annotations table for a configured autocomplete key. The API requires a non-null, non-empty key; null fails fast with NullPointerException('key == null') before any SQL is built. Unlike the Elasticsearch variant, it also requires the key to be in the configured autocompleteKeys set or it returns an empty list.

Source

Thrown at zipkin-storage/mysql-v1/src/main/java/zipkin2/storage/mysql/v1/MySQLAutocompleteTags.java:33

  final boolean enabled;
  final LinkedHashSet<String> autocompleteKeys;
  final Call<List<String>> keysCall;

  MySQLAutocompleteTags(MySQLStorage storage, Schema schema) {
    this.dataSourceCallFactory = storage.dataSourceCallFactory;
    this.schema = schema;
    enabled = storage.searchEnabled && !storage.autocompleteKeys.isEmpty();
    autocompleteKeys = new LinkedHashSet<>(storage.autocompleteKeys);
    keysCall = Call.create(storage.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 || !autocompleteKeys.contains(key)) return Call.emptyList();
    return dataSourceCallFactory.create(new SelectAutocompleteValues(schema, key));
  }
}

View on GitHub (pinned to 878ce2a1fa)

Solutions

  1. Fix the caller to pass a non-null key; find where the null originates (usually an unchecked request parameter).
  2. Validate input at your API boundary: reject or return empty for missing keys.
  3. Remember the key must also be listed in storage.autocompleteKeys to return data.

Example fix

// before
String key = request.getParameter("key");
Call<List<String>> values = storage.autocompleteTags().getValues(key); // NPE when param absent

// 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 respond 400 for a required param
}
Call<List<String>> values = storage.autocompleteTags().getValues(key);

Type guard

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

Prevention

When it happens

Trigger: Calling autocompleteTags().getValues(null) on MySQLStorage, typically by forwarding a missing/unvalidated request parameter straight from an HTTP endpoint.

Common situations: Custom REST facades or UIs over MySQLStorage where ?key= is optional and not checked; refactors that introduce null paths; tests passing null.

Related errors


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