openzipkin/zipkin · error · NullPointerException
executor == null
Error message
executor == null
What it means
MySQLStorage.Builder.executor throws NullPointerException when the java.util.concurrent.Executor argument is null. The executor runs the blocking JDBC work created by DataSourceCall, so async calls (enqueue) would have nowhere to run. The builder fails fast rather than defaulting silently.
Source
Thrown at zipkin-storage/mysql-v1/src/main/java/zipkin2/storage/mysql/v1/MySQLStorage.java:76
public Builder datasource(DataSource datasource) {
if (datasource == null) throw new NullPointerException("datasource == null");
this.datasource = datasource;
return this;
}
public Builder settings(Settings settings) {
if (settings == null) throw new NullPointerException("settings == null");
this.settings = settings;
return this;
}
public Builder listenerProvider(@Nullable ExecuteListenerProvider listenerProvider) {
this.listenerProvider = listenerProvider;
return this;
}
public Builder executor(Executor executor) {
if (executor == null) throw new NullPointerException("executor == null");
this.executor = executor;
return this;
}
@Override public MySQLStorage build() {
return new MySQLStorage(this);
}
Builder() {
}
}
static {
System.setProperty("org.jooq.no-logo", "true");
}
final DataSource datasource;
final DataSourceCall.Factory dataSourceCallFactory;View on GitHub (pinned to 878ce2a1fa)
Solutions
- Pass an explicit executor, e.g. Executors.newSingleThreadExecutor() or a shared application executor such as ForkJoinPool.commonPool().
- Guard at the call site: builder.executor(executor != null ? executor : Runnable::run) for a same-thread fallback.
- If building via zipkin-server Spring configuration, let it build the storage so the executor wiring is handled for you.
Example fix
// before builder.executor(null); // after builder.executor(Executors.newSingleThreadExecutor(daemonThreadFactory));
Defensive patterns
Strategy: validation
Validate before calling
builder.executor(executor != null ? executor : Executors.newSingleThreadExecutor());
Prevention
- Pass an explicit executor and shut it down with the storage component
- Do not assume zipkin builders default optional resources
When it happens
Trigger: Calling builder.executor(null), or forwarding an executor field that was never initialized because async query execution was assumed to be optional.
Common situations: Assuming the builder creates a default executor; wiring an executor bean conditionally in Spring so it is absent in some profiles; refactoring that drops the executor() call but keeps a null variable being passed.
Related errors
AI-assisted analysis of openzipkin/zipkin@878ce2a1fa (2026-08-14).
Data as JSON: /api/errors/c15c4dd46c4a6c49.
Report an issue: GitHub.