lingochamp/FileDownloader · error · FileDownloadGiveUpRetryException
fetched length[ ] != content length[ ], range[ , ) offset[…
Error message
fetched length[%d] != content length[%d], range[%d, %d) offset[%d] fetch begin offset[%d]
What it means
FileDownloadGiveUpRetryException thrown by FetchDataTask.run() after a download chunk finishes: the number of bytes actually fetched does not equal the Content-Length advertised by the server (for non-chunked transfers). The library treats this as a server/range inconsistency it cannot recover from, so it aborts rather than retrying.
Solutions
- Retry the download; if it fails on the same file repeatedly, the server is serving inconsistent Content-Length — verify with curl -r or wget against the URL
- Check for and bypass intermediary proxies/CDN/compression middleware that may alter the body or Range handling
- Ensure the server supports HTTP Range requests correctly (responds 206 with exact requested byte range)
- Update the filedownloader library version; some edge cases around range/offset bookkeeping were fixed over time
- If it only happens on flaky networks, pre-check connectivity and re-issue the download; this exception intentionally disables retry for this attempt
Example fix
// before: single attempt fails hard on flaky network
FileDownloader.getImpl().create(url).setPath(path).start();
// after: catch and re-attempt via listener
FileDownloader.getImpl().create(url).setPath(path)
.setListener(new FileDownloadListener() {
@Override public void warn(FileDownloadBase base, FileDownloadSoFar sofar) {}
@Override public void started(...) {}
// on error, check if bytes fetched mismatch and re-create the task
}).start(); Defensive patterns
Strategy: retry
Validate before calling
// before starting the download, probe the server's range support
HttpURLConnection c = (HttpURLConnection) new URL(url).openConnection();
c.setRequestProperty("Range", "bytes=0-");
if (c.getResponseCode() != 206) {
throw new IllegalStateException("Server does not honor Range; partial download will fail");
}
long declared = c.getContentLength();
if (declared <= 0) {
throw new IllegalStateException("Server reports no usable Content-Length for range request");
} Try / catch
try {
task.start();
} catch (FileDownloadGiveUpRetryException e) {
// fetched bytes != content-length: server inconsistency
log.warn("Body length mismatch, re-issuing download", e);
FileDownloader.getImpl().create(url).setPath(path)
.setListener(listener).start(); // fresh attempt re-syncs offsets
} Prevention
- Verify the URL returns stable Content-Length and correct 206 responses for Range requests (curl -r 0-99 -I)
- Bypass proxies/CDN/gzip middleware that can alter body size between HEAD and GET
- Set a path consistent with prior downloads so offsets stay in sync, or clear stale temp files after version changes
- Keep the filedownloader library up to date; range bookkeeping bugs were fixed in later versions
When it happens
Trigger: The server's response body length differs from the declared Content-Length for the requested Range [startOffset, endOffset); e.g. server truncates the body, closes the connection early, misreports Content-Length, or returns fewer bytes than promised for a resumed range request.
Common situations: Flaky proxies or CDNs cutting connections mid-body; misconfigured servers behind load balancers that strip/alter Range headers; servers that ignore Range and return a different body than expected; unstable mobile networks that end the stream without an error; buggy server-side compression middleware changing body size.
Understand the failure class
Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.
Related errors
- can't know the size of the download file, and its…
- connection is null when findEtag
- The filename [ ] from the response is not allowable…
- response code error: , request headers: response headers
- Connection failed with request
AI-assisted analysis of lingochamp/FileDownloader@6237a8cac1 (2026-09-08).
Data as JSON: /api/errors/9e9868dc1e1ae065.
Report an issue: GitHub.
Appendix: source
Thrown at library/src/main/java/com/liulishuo/filedownloader/download/FetchDataTask.java:190
}
try {
if (outputStream != null) sync();
} finally {
if (outputStream != null) {
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
final long fetchedLength = currentOffset - fetchBeginOffset;
if (contentLength != TOTAL_VALUE_IN_CHUNKED_RESOURCE && contentLength != fetchedLength) {
throw new FileDownloadGiveUpRetryException(
FileDownloadUtils.formatString("fetched length[%d] != content length[%d],"
+ " range[%d, %d) offset[%d] fetch begin offset[%d]",
fetchedLength, contentLength,
startOffset, endOffset, currentOffset, fetchBeginOffset));
}
// callback completed
callback.onCompleted(hostRunnable, startOffset, endOffset);
}
private final FileDownloadDatabase database;
private volatile long lastSyncBytes = 0;
private volatile long lastSyncTimestamp = 0;
private void checkAndSync() {
final long now = SystemClock.elapsedRealtime();
final long bytesDelta = currentOffset - lastSyncBytes;
final long timestampDelta = now - lastSyncTimestamp;View on GitHub (pinned to 6237a8cac1)