{"record":{"id":"b2187c445d29c459","repo":"didi/DoKit","slug":"executor-service-already-set","errorCode":null,"errorMessage":"Executor service already set.","messagePattern":"Executor service already set\\.","errorType":"validation","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"Android/dokit/src/main/java/com/didichuxing/doraemonkit/picasso/DokitPicasso.java","lineNumber":741,"sourceCode":"      }\n      if (this.downloader != null) {\n        throw new IllegalStateException(\"Downloader already set.\");\n      }\n      this.downloader = downloader;\n      return this;\n    }\n\n    /**\n     * Specify the executor service for loading images in the background.\n     * <p>\n     * Note: Calling {@link DokitPicasso#shutdown() shutdown()} will not shutdown supplied executors.\n     */\n    public Builder executor(ExecutorService executorService) {\n      if (executorService == null) {\n        throw new IllegalArgumentException(\"Executor service must not be null.\");\n      }\n      if (this.service != null) {\n        throw new IllegalStateException(\"Executor service already set.\");\n      }\n      this.service = executorService;\n      return this;\n    }\n\n    /** Specify the memory cache used for the most recent images. */\n    public Builder memoryCache(Cache memoryCache) {\n      if (memoryCache == null) {\n        throw new IllegalArgumentException(\"Memory cache must not be null.\");\n      }\n      if (this.cache != null) {\n        throw new IllegalStateException(\"Memory cache already set.\");\n      }\n      this.cache = memoryCache;\n      return this;\n    }\n\n    /** Specify a listener for interesting events. */","sourceCodeStart":723,"sourceCodeEnd":759,"githubUrl":"https://github.com/didi/DoKit/blob/626827cddb2feb2f3aee87a52a064b4e5ca2bed4/Android/dokit/src/main/java/com/didichuxing/doraemonkit/picasso/DokitPicasso.java#L723-L759","documentation":"DokitPicasso.Builder.executor() throws IllegalStateException when an ExecutorService has already been set on this builder. Like the other Builder components, the executor is single-assignment to prevent silent replacement of a configured component.","triggerScenarios":"Calling builder.executor(...) twice on the same Builder instance, e.g. a default executor set in a base init method and a custom one set later by an app-specific init.","commonSituations":"Library initialization code that sets an executor, plus app-level code that sets another; refactors that added a second executor() call without removing the first.","solutions":["Ensure executor() is called at most once per Builder","Consolidate executor selection into one place (single init method)","Use a new Builder if the whole configuration must be redone"],"exampleFix":"// before\nbuilder.executor(defaultExecutor);\nbuilder.executor(customExecutor); // IllegalStateException\n\n// after\nbuilder.executor(customExecutor);","handlingStrategy":"validation","validationCode":"// Configure executor in exactly one place\nbuilder.executor(Executors.newFixedThreadPool(4)); // single call site","typeGuard":null,"tryCatchPattern":"try { builder.executor(s); } catch (IllegalStateException e) { if (!e.getMessage().contains(\"Executor service already set\")) throw e; }","preventionTips":["Centralize builder configuration; audit for duplicate executor() calls when merging init code"],"tags":["android","picasso","builder","configuration"],"backgroundTag":null,"analyzedSha":"626827cddb2feb2f3aee87a52a064b4e5ca2bed4","analyzedAt":"2026-08-14T12:45:58.758Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}