didi/DoKit · error · IllegalStateException
Downloader already set.
Error message
Downloader already set.
What it means
DokitPicasso.Builder.downloader() throws IllegalStateException when a Downloader has already been assigned to this builder. The builder enforces one-shot configuration for each component to avoid silently replacing a configured downloader. This mirrors upstream Picasso's builder contract.
Source
Thrown at Android/dokit/src/main/java/com/didichuxing/doraemonkit/picasso/DokitPicasso.java:725
/**
* Specify the default {@link Bitmap.Config} used when decoding images. This can be overridden
* on a per-request basis using {@link RequestCreator#config(Bitmap.Config) config(..)}.
*/
public Builder defaultBitmapConfig(Bitmap.Config bitmapConfig) {
if (bitmapConfig == null) {
throw new IllegalArgumentException("Bitmap config must not be null.");
}
this.defaultBitmapConfig = bitmapConfig;
return this;
}
/** Specify the {@link Downloader} that will be used for downloading images. */
public Builder downloader(Downloader downloader) {
if (downloader == null) {
throw new IllegalArgumentException("Downloader must not be null.");
}
if (this.downloader != null) {
throw new IllegalStateException("Downloader already set.");
}
this.downloader = downloader;
return this;
}
/**
* Specify the executor service for loading images in the background.
* <p>
* Note: Calling {@link DokitPicasso#shutdown() shutdown()} will not shutdown supplied executors.
*/
public Builder executor(ExecutorService executorService) {
if (executorService == null) {
throw new IllegalArgumentException("Executor service must not be null.");
}
if (this.service != null) {
throw new IllegalStateException("Executor service already set.");
}
this.service = executorService;View on GitHub (pinned to 626827cddb)
Solutions
- Remove the duplicate downloader() call so it is invoked exactly once per Builder
- If you need to replace a downloader, create a fresh Builder and configure it once
- Track whether the builder was already configured before calling downloader() again
Example fix
// before builder.downloader(defaultDownloader); builder.downloader(new OkHttp3Downloader(client)); // IllegalStateException // after builder.downloader(new OkHttp3Downloader(client));
Defensive patterns
Strategy: validation
Validate before calling
// Set the downloader exactly once; track it yourself
if (builderHasDownloader) { throw new IllegalStateException("configure downloader once"); }
builder.downloader(new OkHttp3Downloader(client));
builderHasDownloader = true; Try / catch
try { builder.downloader(d); } catch (IllegalStateException e) { if (!e.getMessage().contains("Downloader already set")) throw e; log("downloader already configured"); } Prevention
- Build the entire Picasso configuration in one method so each component is set exactly once
- Never share a Builder across init layers without ownership rules
- Treat builder IllegalStateExceptions as programming errors to fix, not to catch
When it happens
Trigger: Calling builder.downloader(d) a second time on the same Builder instance, e.g. applying a default downloader and then overriding it with a custom OkHttp downloader.
Common situations: Copy-pasted configuration code that sets a downloader in two places; a shared builder passed through several config methods; upgrading code that injected a new downloader without removing the old call.
Related errors
- Executor service already set.
- Memory cache already set.
- Listener already set.
- Transformer already set.
- RequestHandler already registered.
AI-assisted analysis of didi/DoKit@626827cddb (2026-08-14).
Data as JSON: /api/errors/3cd8607450ac424f.
Report an issue: GitHub.