openzipkin/zipkin · error · IllegalArgumentException
maxTraceCols <= 0
Error message
maxTraceCols <= 0
What it means
Thrown by CassandraStorageBuilder.maxTraceCols(int) when the value is zero or negative. maxTraceCols caps how many span rows are fetched per trace id because a single span id can have multiple rows (client and server share a span id). The guard prevents an unbounded or nonsensical fetch size.
Source
Thrown at zipkin-storage/cassandra/src/main/java/zipkin2/storage/cassandra/CassandraStorageBuilder.java:176
}
public B ensureSchema(boolean ensureSchema) {
if (ensureSchema) {
this.ensureSchema = Schema::ensure;
} else {
this.ensureSchema = Schema::validate;
}
return (B) this;
}
/**
* Spans have multiple values for the same id. For example, a client and server contribute to the
* same span id. When searching for spans by id, the amount of results may be larger than the ids.
* This defines a threshold which accommodates this situation, without looking for an unbounded
* number of results.
*/
public B maxTraceCols(int maxTraceCols) {
if (maxTraceCols <= 0) throw new IllegalArgumentException("maxTraceCols <= 0");
this.maxTraceCols = maxTraceCols;
return (B) this;
}
/**
* How many more index rows to fetch than the user-supplied query limit. Defaults to 3.
*
* <p>Backend requests will request {@link QueryRequest#limit()} times this factor rows from
* Cassandra indexes in attempts to return {@link QueryRequest#limit()} traces.
*
* <p>Indexing in cassandra will usually have more rows than trace identifiers due to factors
* including table design and collection implementation. As there's no way to DISTINCT out
* duplicates server-side, this over-fetches client-side when {@code indexFetchMultiplier} >
* 1.
*/
public B indexFetchMultiplier(int indexFetchMultiplier) {
if (indexFetchMultiplier <= 0) throw new IllegalArgumentException("indexFetchMultiplier <= 0");
this.indexFetchMultiplier = indexFetchMultiplier;View on GitHub (pinned to 878ce2a1fa)
Solutions
- Set a positive value, e.g. maxTraceCols(10000) (the documented default is 10000).
- Validate the config-sourced integer before passing it: reject or default values <= 0 at load time.
Example fix
// before
.maxTraceCols(Integer.parseInt(System.getenv("MAX_TRACE_COLS"))) // env unset -> 0
// after
int maxTraceCols = Integer.parseInt(System.getenv().getOrDefault("MAX_TRACE_COLS", "10000"));
if (maxTraceCols <= 0) throw new IllegalArgumentException("MAX_TRACE_COLS must be > 0");
.maxTraceCols(maxTraceCols) Defensive patterns
Strategy: validation
Validate before calling
int maxTraceCols = config.getInt("cassandra.max-trace-cols", 10000);
if (maxTraceCols <= 0) throw new IllegalArgumentException("maxTraceCols must be > 0, got " + maxTraceCols);
builder.maxTraceCols(maxTraceCols); Prevention
- Validate positive-integer config values at load time with clear messages including the property name.
- Omit the setter entirely to keep the documented default.
When it happens
Trigger: Calling maxTraceCols(0) or maxTraceCols(-5) on CassandraStorage.newBuilder(); computing the value from user input or config that defaulted to 0 when parsing failed.
Common situations: Setting maxTraceCols from an environment variable or properties file where a typo or missing value parses to 0; porting older configs that used a different name.
Related errors
- clientProps is empty
- consumerProps is empty
- maxConnections <= 0
- sessionFactory == null
- indexFetchMultiplier <= 0
AI-assisted analysis of openzipkin/zipkin@878ce2a1fa (2026-08-14).
Data as JSON: /api/errors/71205b2c2a0f3be0.
Report an issue: GitHub.