lingochamp/FileDownloader · error · FileDownloadHttpException

response code error: , request headers: response headers

Error message

response code error: %d, 
 request headers: %s 
 response headers: %s

What it means

FileDownloadHttpException is thrown by DownloadLaunchRunnable.handleTrialConnectResult when the server's HTTP response code is not acceptable for the trial/redirect connection (not 206 Partial Content or 200 OK). It carries the HTTP status code plus the full request and response headers so the developer can diagnose the server-side rejection. This is the library's way of surfacing that the remote server refused or mishandled the download request.

Solutions

  1. Log/inspect the request and response headers attached to the exception to see exactly how the server rejected the request
  2. Verify the URL is still valid and returns the file directly (test with curl -I)
  3. Check whether the server honors Range requests; disable resume/trial download (FileDownloadProperties isTrialCancelled or remove range headers) if it returns 416
  4. Add required authentication headers/cookies to the request via FileDownloadListener addHeader or ConnectTask header setup
  5. Retry on 5xx with backoff; fix server-side issue or use a mirror URL

Example fix

// before: downloading an expired pre-signed URL
FileDownloader.getImpl().create(url).setPath(path).start();
// after: refresh the URL and add required headers before downloading
String freshUrl = refreshSignedUrl(url);
FileDownloader.getImpl().create(freshUrl)
    .addHeader("Authorization", token)
    .setPath(path)
    .start();
Defensive patterns

Strategy: try-catch

Validate before calling

HttpURLConnection c = (HttpURLConnection) new URL(url).openConnection();
c.setRequestMethod("HEAD");
int code = c.getResponseCode();
if (code != 200 && code != 206) throw new IllegalStateException("URL not downloadable, code=" + code);

Try / catch

try {
    FileDownloader.getImpl().create(url).setPath(path).start(listener);
} catch (FileDownloadHttpException e) {
    // e.getCode(), e.getRequestHeader(), e.getResponseHeader() for diagnostics
    Log.e(TAG, "download failed with HTTP " + ((FileDownloadHttpException) e).getCode(), e);
}

Prevention

When it happens

Trigger: The server responds to the download (or 'Accept-Ranges' trial) request with a status code other than HTTP 200/206 — e.g. 403 Forbidden, 404 Not Found, 416 Range Not Satisfiable, 5xx server errors, or a redirect loop — after FileDownloader has opened the HttpURLConnection.

Common situations: URL points to a page that returns 404/403 instead of a file; CDN or server rejects Range requests (416); expired signed URLs (S3 pre-signed links returning 403); server requiring auth cookies/headers not supplied; proxy/firewall returning HTML error pages.

Understand the failure class

Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.

Related errors


AI-assisted analysis of lingochamp/FileDownloader@6237a8cac1 (2026-09-08). Data as JSON: /api/errors/d27dbceb1ecf4243. Report an issue: GitHub.

Appendix: source

Thrown at library/src/main/java/com/liulishuo/filedownloader/download/DownloadLaunchRunnable.java:571

        redirectedUrl = connectTask.getFinalRedirectedUrl();
        if (acceptPartial || onlyFromBeginning) {


            // update model
            String fileName = null;
            if (model.isPathAsDirectory()) {
                // filename
                fileName = FileDownloadUtils.findFilename(connection, model.getUrl());
            }
            isChunked = (totalLength == TOTAL_VALUE_IN_CHUNKED_RESOURCE);

            // callback
            statusCallback.onConnected(isResumeAvailableOnDB && acceptPartial,
                    totalLength, newEtag, fileName);

        } else {
            throw new FileDownloadHttpException(code,
                    requestHeader, connection.getResponseHeaderFields());
        }
    }

    private void realDownloadWithSingleConnection(final long totalLength)
            throws IOException, IllegalAccessException {

        // connect
        final ConnectionProfile profile;
        if (!acceptPartial) {
            model.setSoFar(0);
            profile = ConnectionProfile.ConnectionProfileBuild
                    .buildBeginToEndConnectionProfile(totalLength);
        } else {
            profile = ConnectionProfile.ConnectionProfileBuild
                    .buildToEndConnectionProfile(model.getSoFar(), model.getSoFar(),
                            totalLength - model.getSoFar());
        }

View on GitHub (pinned to 6237a8cac1)