{"record":{"id":"bf406fa8df048325","repo":"HMCL-dev/HMCL","slug":"unexpected-file-size-downloaded-expected-con","errorCode":null,"errorMessage":"Unexpected file size: <downloaded>, expected: <contentLength>","messagePattern":"Unexpected file size: <downloaded>, expected: <contentLength>","errorType":"exception","errorClass":"java.io.IOException","httpStatus":null,"severity":"error","filePath":"HMCLCore/src/main/java/org/jackhuang/hmcl/task/FetchTask.java","lineNumber":272,"sourceCode":"                if (resume != null)\n                    resume.countUncompressed += len;\n\n                if (contentLength >= 0) {\n                    // Update progress information per second\n                    updateProgress(counter.downloaded, contentLength);\n                }\n\n                updateDownloadSpeed(counter.downloaded - lastDownloaded);\n                lastDownloaded = counter.downloaded;\n            }\n\n            if (isCancelled())\n                throw new InterruptedException();\n\n            updateDownloadSpeed(counter.downloaded - lastDownloaded);\n\n            if (contentLength >= 0 && counter.downloaded != contentLength)\n                throw new IOException(\"Unexpected file size: \" + counter.downloaded + \", expected: \" + contentLength);\n\n            success = true;\n        }\n\n        if (success) {\n            context.withResult(true);\n        }\n    }\n\n    private void downloadHttp(URI uri, boolean checkETag) throws DownloadException, InterruptedException {\n        if (checkETag) {\n            // Handle cache\n            try {\n                Path cache = repository.getCachedRemoteFile(uri, true);\n                useCachedResult(cache);\n                LOG.info(\"Using cached file for \" + NetworkUtils.dropQuery(uri));\n                return;\n            } catch (IOException ignored) {","sourceCodeStart":254,"sourceCodeEnd":290,"githubUrl":"https://github.com/HMCL-dev/HMCL/blob/24702dc5a0214034f4c27166d5fd30cad08cec19/HMCLCore/src/main/java/org/jackhuang/hmcl/task/FetchTask.java#L254-L290","documentation":"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.","triggerScenarios":"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.","commonSituations":"Flaky Wi-Fi or mobile connections; overloaded mirrors (especially third-party Minecraft download mirrors); intermediaries that gzip or cut responses incorrectly.","solutions":["Simply retry the download — FetchTask's callers typically retry transient truncations","Check network stability / switch mirror or proxy","Verify server or CDN is not mangling content-length (e.g. compression middleware)","If persistent, compare the file against its checksum to detect systematic truncation"],"exampleFix":"// before\nfetchTask.run(); // may throw on truncation\n// after\ntry {\n    fetchTask.run();\n} catch (IOException e) {\n    if (e.getMessage().startsWith(\"Unexpected file size\")) retryWithBackoff(fetchTask);\n    else throw e;\n}","handlingStrategy":"retry","validationCode":"long expected = responseInfo.headers().firstValueAsLong(\"content-length\").orElse(-1L);\nif (expected >= 0) verifyDownloadedSize(file, expected); // pre/post check","typeGuard":null,"tryCatchPattern":"try {\n    fetchTask.run();\n} catch (IOException e) {\n    if (e.getMessage().startsWith(\"Unexpected file size\")) retryWithBackoff(fetchTask, 3);\n    else throw e;\n}","preventionTips":["Use mirrors on stable network paths","Verify final checksums after download as a second line of defense","Monitor for specific mirrors with chronic truncation and drop them"],"tags":["download","http","truncated-transfer","network"],"backgroundTag":"http-request-failed","analyzedSha":"24702dc5a0214034f4c27166d5fd30cad08cec19","analyzedAt":"2026-09-10T12:36:46.680Z","contentChangedAt":"2026-09-10T12:36:46.680Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}