HMCL-dev/HMCL · error · java.io.IOException

Unexpected file size

Error message

Unexpected file size: <downloaded>, expected: <contentLength>

What it means

FetchTask.download() counts bytes as they arrive and, when the server reported a non-negative content-length, verifies the downloaded byte count matches exactly. This IOException is thrown when the connection closed with fewer (or more) bytes than the advertised content-length, i.e. a truncated or corrupted transfer.

Solutions

  1. Simply retry the download — FetchTask's callers typically retry transient truncations
  2. Check network stability / switch mirror or proxy
  3. Verify server or CDN is not mangling content-length (e.g. compression middleware)
  4. If persistent, compare the file against its checksum to detect systematic truncation

Example fix

// before
fetchTask.run(); // may throw on truncation
// after
try {
    fetchTask.run();
} catch (IOException e) {
    if (e.getMessage().startsWith("Unexpected file size")) retryWithBackoff(fetchTask);
    else throw e;
}
Defensive patterns

Strategy: retry

Validate before calling

long expected = responseInfo.headers().firstValueAsLong("content-length").orElse(-1L);
if (expected >= 0) verifyDownloadedSize(file, expected); // pre/post check

Try / catch

try {
    fetchTask.run();
} catch (IOException e) {
    if (e.getMessage().startsWith("Unexpected file size")) retryWithBackoff(fetchTask, 3);
    else throw e;
}

Prevention

When it happens

Trigger: Server closes the connection mid-transfer; proxy or CDN truncates the body; network drop during download; content-length header disagrees with the actual body size.

Common situations: Flaky Wi-Fi or mobile connections; overloaded mirrors (especially third-party Minecraft download mirrors); intermediaries that gzip or cut responses incorrectly.

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


AI-assisted analysis of HMCL-dev/HMCL@24702dc5a0 (2026-09-10). Data as JSON: /api/errors/bf406fa8df048325. Report an issue: GitHub.

Appendix: source

Thrown at HMCLCore/src/main/java/org/jackhuang/hmcl/task/FetchTask.java:272

                if (resume != null)
                    resume.countUncompressed += len;

                if (contentLength >= 0) {
                    // Update progress information per second
                    updateProgress(counter.downloaded, contentLength);
                }

                updateDownloadSpeed(counter.downloaded - lastDownloaded);
                lastDownloaded = counter.downloaded;
            }

            if (isCancelled())
                throw new InterruptedException();

            updateDownloadSpeed(counter.downloaded - lastDownloaded);

            if (contentLength >= 0 && counter.downloaded != contentLength)
                throw new IOException("Unexpected file size: " + counter.downloaded + ", expected: " + contentLength);

            success = true;
        }

        if (success) {
            context.withResult(true);
        }
    }

    private void downloadHttp(URI uri, boolean checkETag) throws DownloadException, InterruptedException {
        if (checkETag) {
            // Handle cache
            try {
                Path cache = repository.getCachedRemoteFile(uri, true);
                useCachedResult(cache);
                LOG.info("Using cached file for " + NetworkUtils.dropQuery(uri));
                return;
            } catch (IOException ignored) {

View on GitHub (pinned to 24702dc5a0)