didi/DoKit · error · IllegalArgumentException
Downloader must not be null.
Error message
Downloader must not be null.
What it means
Builder.downloader(Downloader) sets the network layer; null is rejected with IllegalArgumentException('Downloader must not be null.') (and a second call with IllegalStateException 'Downloader already set.'). Picasso needs a concrete downloader to fetch remote URLs — there is no default-null mode — so the guard fires at build configuration time rather than at first network request.
Source
Thrown at Android/dokit/src/main/java/com/didichuxing/doraemonkit/picasso/DokitPicasso.java:722
this.context = context.getApplicationContext();
}
/**
* 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) {View on GitHub (pinned to 626827cddb)
Solutions
- Always pass a real Downloader: new OkHttp3Downloader(client) or new UrlConnectionDownloader()
- If DI provides it, make the provider non-nullable and fail at graph construction
- To block network in tests, supply a Downloader whose load() throws IOException — not null
Example fix
// before
new DokitPicasso.Builder(context)
.downloader(injectedDownloader) // null when DI module missed
.build();
// after
new DokitPicasso.Builder(context)
.downloader(injectedDownloader != null
? injectedDownloader
: new okhttp3.OkHttp3Downloader(new OkHttpClient()))
.build(); Defensive patterns
Strategy: validation
Validate before calling
Downloader dl = (injectedDownloader != null)
? injectedDownloader
: new okhttp3.OkHttp3Downloader(new OkHttpClient());
DokitPicasso picasso = new DokitPicasso.Builder(context).downloader(dl).build(); Try / catch
try {
builder.downloader(downloader);
} catch (IllegalArgumentException e) {
if ("Downloader must not be null.".equals(e.getMessage())) {
builder.downloader(new okhttp3.OkHttp3Downloader(new OkHttpClient()));
} else throw e;
} Prevention
- Pass a concrete Downloader (OkHttp3Downloader or UrlConnectionDownloader) every time
- Make DI providers non-nullable so misconfiguration fails at build time in the graph
- To disable networking in tests, use a Downloader that throws IOException — never null
When it happens
Trigger: builder.downloader(null) from an injection field that is not yet populated; passing a Downloader obtained from a lazy provider that returned null; test code stubbing the downloader as null to 'disable' networking (use a mock that throws instead).
Common situations: DI module supplying null when a flavor lacks the OkHttp dependency; replacing UrlConnectionDownloader with a custom one whose factory fails silently.
Related errors
- Bitmap config must not be null.
- namesAndValues == null
- Headers cannot be null
- headers == null
- name == null
AI-assisted analysis of didi/DoKit@626827cddb (2026-08-14).
Data as JSON: /api/errors/06768cfb4dd4fb44.
Report an issue: GitHub.