lingochamp/FileDownloader · error · IllegalArgumentException
the download runnable must not be null!
Error message
the download runnable must not be null!
What it means
An IllegalArgumentException thrown in DownloadLaunchRunnable.fetchWithMultipleConnection when one of the per-range DownloadRunnable instances built for a multi-connection download is null. This is an internal invariant check: every slice of a multi-connection download must have a runnable before it is added to downloadRunnableList. Seeing it usually means the connection model list or runnable creation produced a null entry, typically due to corrupted breakpoint models.
Solutions
- Clear the download's breakpoint data (FileDownloader.getImpl().clear(taskId, path)) and restart the download from scratch
- Ensure the target file path and task are removed from the FileDownloader DB before resuming (delete the file and re-create the task)
- Check for concurrent downloads of the same ID/path from multiple processes and serialize them (use FileDownloadActivity/Service or a global lock)
- Upgrade to the latest FileDownloader version, which hardens breakpoint model consistency
- If reproducible, file a bug with the DB contents for the task ID
Example fix
// before: blindly resuming a possibly-corrupt task FileDownloader.getImpl().create(url).setPath(path).start(); // after: clear stale breakpoint state when resuming fails FileDownloader.getImpl().clear(taskId, path); new File(path + ".temp").delete(); FileDownloader.getImpl().create(url).setPath(path).start();
Defensive patterns
Strategy: validation
Validate before calling
// Before resuming, ensure breakpoint state is consistent
FileDownloadTask task = FileDownloader.getImpl().create(url).setPath(path);
File temp = new File(path + ".temp");
if (!temp.exists()) {
FileDownloader.getImpl().clear(taskId, path); // drop stale breakpoint rows
} Try / catch
try {
FileDownloader.getImpl().create(url).setPath(path).start(listener);
} catch (IllegalArgumentException e) {
FileDownloader.getImpl().clear(taskId, path);
new File(path + ".temp").delete();
FileDownloader.getImpl().create(url).setPath(path).start(listener); // fresh start
} Prevention
- Clear breakpoint data whenever the .temp file is missing or the DB row looks stale
- Avoid downloading the same task ID/path from multiple processes concurrently
- Keep FileDownloader upgraded to versions with breakpoint-consistency fixes
- Validate any restored task state before resuming
When it happens
Trigger: Resuming a download with multiple connections where the stored breakpoint/connection models (ConnectionModel from the database) are inconsistent or partially deleted, so a range chunk gets no runnable assigned before fetchWithMultipleConnection iterates the chunks.
Common situations: Database corruption or a version upgrade of FileDownloader leaving stale/invalid breakpoint records; resuming a task whose .temp file or breakpoint DB row was deleted mid-flight; concurrent access to the same download ID from multiple processes.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- can't handover the message, no master to receive this…
- response code error: , request headers: response headers
- The file is too large to store, breakpoint in bytes
- Task[ ] can't start the download runnable, because this…
- Connection failed with request
AI-assisted analysis of lingochamp/FileDownloader@6237a8cac1 (2026-09-08).
Data as JSON: /api/errors/296e06db8503038c.
Report an issue: GitHub.
Appendix: source
Thrown at library/src/main/java/com/liulishuo/filedownloader/download/DownloadLaunchRunnable.java:726
final DownloadRunnable runnable = builder
.setId(id)
.setConnectionIndex(connectionModel.getIndex())
.setCallback(this)
.setUrl(url)
.setEtag(withEtag ? etag : null)
.setHeader(userRequestHeader)
.setWifiRequired(isWifiRequired)
.setConnectionModel(connectionProfile)
.setPath(path)
.build();
if (FileDownloadLog.NEED_LOG) {
FileDownloadLog.d(this, "enable multiple connection: %s", connectionModel);
}
if (runnable == null) {
throw new IllegalArgumentException("the download runnable must not be null!");
}
downloadRunnableList.add(runnable);
}
if (totalOffset != model.getSoFar()) {
FileDownloadLog.w(this, "correct the sofar[%d] from connection table[%d]",
model.getSoFar(), totalOffset);
model.setSoFar(totalOffset);
}
List<Callable<Object>> subTasks = new ArrayList<>(downloadRunnableList.size());
for (DownloadRunnable runnable : downloadRunnableList) {
if (paused) {
runnable.pause();
continue;
}
subTasks.add(Executors.callable(runnable));View on GitHub (pinned to 6237a8cac1)