openzipkin/zipkin · error · NullPointerException

key == null

Error message

key == null

What it means

Span.Builder.putTag(String key, String value) throws NullPointerException when key is null ('key == null'), and a second NPE with message 'value of <key> == null' for a null value. Tags are stored in a TreeMap keyed by string, so null keys would break sorting and serialization. Both arguments are always required.

Source

Thrown at zipkin/src/main/java/zipkin2/Span.java:537

    /** Sets {@link Span#annotations} */
    public Builder addAnnotation(long timestamp, String value) {
      if (annotations == null) annotations = new ArrayList<>(2);
      annotations.add(Annotation.create(timestamp, value));
      return this;
    }

    /** Sets {@link Span#annotations} */
    public Builder clearAnnotations() {
      if (annotations == null) return this;
      annotations.clear();
      return this;
    }

    /** Sets {@link Span#tags} */
    public Builder putTag(String key, String value) {
      if (tags == null) tags = new TreeMap<>();
      if (key == null) throw new NullPointerException("key == null");
      if (value == null) throw new NullPointerException("value of " + key + " == null");
      this.tags.put(key, value);
      return this;
    }

    /** Sets {@link Span#tags} */
    public Builder clearTags() {
      if (tags == null) return this;
      tags.clear();
      return this;
    }

    /** Sets {@link Span#debug} */
    public Builder debug(boolean debug) {
      flags |= FLAG_DEBUG_SET;
      if (debug) {
        flags |= FLAG_DEBUG;
      } else {

View on GitHub (pinned to 878ce2a1fa)

Solutions

  1. Filter null keys and values before putting: if (k != null && v != null) b.putTag(k, v).
  2. Convert null values to a sentinel string ("null" or "") if you want to record the field's absence explicitly.
  3. Where the null originates from optional request state, skip tagging that attribute entirely.

Example fix

// before
for (Map.Entry<String,String> e : attributes.entrySet()) {
  b.putTag(e.getKey(), e.getValue());
}

// after
for (Map.Entry<String,String> e : attributes.entrySet()) {
  if (e.getKey() != null && e.getValue() != null) b.putTag(e.getKey(), e.getValue());
}
Defensive patterns

Strategy: validation

Validate before calling

for (Map.Entry<String,String> e : attrs.entrySet()) {
  if (e.getKey() != null && e.getValue() != null) b.putTag(e.getKey(), e.getValue());
}

Prevention

When it happens

Trigger: Calling putTag(null, "v"), putTag(k, map.get(missingKey)), or looping over a Map<String,String> that legitimately contains null keys/values (e.g. from JSON parsing or JDBC result maps).

Common situations: Tagging loops over request headers, system properties, or ORM rows where null values are legal in the source map; conditional tagging code where the key is built from optional request fields (e.g. "http.path" from a null URI).

Related errors


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