{"record":{"id":"c15c4dd46c4a6c49","repo":"openzipkin/zipkin","slug":"executor-null","errorCode":null,"errorMessage":"executor == null","messagePattern":"executor == null","errorType":"validation","errorClass":"NullPointerException","httpStatus":null,"severity":"error","filePath":"zipkin-storage/mysql-v1/src/main/java/zipkin2/storage/mysql/v1/MySQLStorage.java","lineNumber":76,"sourceCode":"    public Builder datasource(DataSource datasource) {\n      if (datasource == null) throw new NullPointerException(\"datasource == null\");\n      this.datasource = datasource;\n      return this;\n    }\n\n    public Builder settings(Settings settings) {\n      if (settings == null) throw new NullPointerException(\"settings == null\");\n      this.settings = settings;\n      return this;\n    }\n\n    public Builder listenerProvider(@Nullable ExecuteListenerProvider listenerProvider) {\n      this.listenerProvider = listenerProvider;\n      return this;\n    }\n\n    public Builder executor(Executor executor) {\n      if (executor == null) throw new NullPointerException(\"executor == null\");\n      this.executor = executor;\n      return this;\n    }\n\n    @Override public MySQLStorage build() {\n      return new MySQLStorage(this);\n    }\n\n    Builder() {\n    }\n  }\n\n  static {\n    System.setProperty(\"org.jooq.no-logo\", \"true\");\n  }\n\n  final DataSource datasource;\n  final DataSourceCall.Factory dataSourceCallFactory;","sourceCodeStart":58,"sourceCodeEnd":94,"githubUrl":"https://github.com/openzipkin/zipkin/blob/878ce2a1fad54ca941d17fdcf2e1d924b148eb1f/zipkin-storage/mysql-v1/src/main/java/zipkin2/storage/mysql/v1/MySQLStorage.java#L58-L94","documentation":"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.","triggerScenarios":"Calling builder.executor(null), or forwarding an executor field that was never initialized because async query execution was assumed to be optional.","commonSituations":"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.","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."],"exampleFix":"// before\nbuilder.executor(null);\n\n// after\nbuilder.executor(Executors.newSingleThreadExecutor(daemonThreadFactory));","handlingStrategy":"validation","validationCode":"builder.executor(executor != null ? executor : Executors.newSingleThreadExecutor());","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Pass an explicit executor and shut it down with the storage component","Do not assume zipkin builders default optional resources"],"tags":["mysql","storage","builder","null-pointer","executor","concurrency"],"backgroundTag":null,"analyzedSha":"878ce2a1fad54ca941d17fdcf2e1d924b148eb1f","analyzedAt":"2026-08-14T15:17:09.895Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}