openzipkin/zipkin · error · IllegalArgumentException

maxSpanCount <= 0

Error message

maxSpanCount <= 0

What it means

InMemoryStorage.Builder.maxSpanCount(int) sets the eviction threshold for the in-memory store (eldest traces are evicted to keep span count bounded) and requires a positive value; zero or negative throws IllegalArgumentException('maxSpanCount <= 0'). This is a fail-fast configuration check at builder time, not a runtime data error.

Source

Thrown at zipkin/src/main/java/zipkin2/storage/InMemoryStorage.java:89

    @Override public Builder strictTraceId(boolean strictTraceId) {
      this.strictTraceId = strictTraceId;
      return this;
    }

    @Override public Builder searchEnabled(boolean searchEnabled) {
      this.searchEnabled = searchEnabled;
      return this;
    }

    @Override public Builder autocompleteKeys(List<String> autocompleteKeys) {
      if (autocompleteKeys == null) throw new NullPointerException("autocompleteKeys == null");
      this.autocompleteKeys = autocompleteKeys;
      return this;
    }

    /** Eldest traces are removed to ensure spans in memory don't exceed this value */
    public Builder maxSpanCount(int maxSpanCount) {
      if (maxSpanCount <= 0) throw new IllegalArgumentException("maxSpanCount <= 0");
      this.maxSpanCount = maxSpanCount;
      return this;
    }

    @Override public InMemoryStorage build() {
      return new InMemoryStorage(this);
    }
  }

  /**
   * Primary source of data is this map, which includes spans ordered descending by timestamp. All
   * other maps are derived from the span values here. This uses a list for the spans, so that it is
   * visible (via /api/v2/trace/{traceId}) when instrumentation report the same spans multiple
   * times.
   */
  private final SortedMultimap<TraceIdTimestamp, Span> spansByTraceIdTimestamp =
    new SortedMultimap<TraceIdTimestamp, Span>(TIMESTAMP_DESCENDING) {
      @Override Collection<Span> valueContainer() {

View on GitHub (pinned to 878ce2a1fa)

Solutions

  1. Set a positive value matching expected volume (e.g. 500000) via the builder or the zipkin-server property.
  2. Trace where the 0 came from: log the property source; fix the typo (zipkin.storage.mem.maxspans) or supply the env var.
  3. Guard computed values: maxSpanCount(Math.max(1, configured)).
  4. Fail startup with a clear message instead of silently defaulting unset config to 0.

Example fix

# before (zipkin-server env)
# ZIPKIN_STORAGE_MEM_MAXSPANS unset -> builder got 0

# after
ZIPKIN_STORAGE_MEM_MAXSPANS=500000
Defensive patterns

Strategy: validation

Validate before calling

int effective = configuredMaxSpans > 0 ? configuredMaxSpans : 500_000;
InMemoryStorage storage = InMemoryStorage.newBuilder().maxSpanCount(effective).build();

Type guard

boolean isValidMaxSpanCount(int v) { return v > 0; }

Prevention

When it happens

Trigger: Calling new InMemoryStorage.Builder().maxSpanCount(0) (or a negative), usually because a config property (zipkin.storage.mem.maxSpans) failed to resolve and defaulted to 0, or arithmetic computed the value.

Common situations: Property name typo so the configured value never lands and an int default of 0 is passed; env-var missing in a deployment; tests parameterizing maxSpanCount with an unset value.

Related errors


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