{"record":{"id":"4f8cdb5705f048b5","repo":"TeamNewPipe/NewPipe","slug":"invalid-file-length-expected-s-found-s","errorCode":null,"errorMessage":"invalid file length. expected = %s  found = %s","messagePattern":"invalid file length\\. expected = (.+?)  found = (.+?)","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"app/src/main/java/us/shandian/giga/io/ChunkFileInputStream.java","lineNumber":32,"sourceCode":"\n    private long progressReport;\n    private final ProgressReport onProgress;\n\n    public ChunkFileInputStream(SharpStream target, long start, long end, ProgressReport callback) throws IOException {\n        source = target;\n        offset = start;\n        length = end - start;\n        position = 0;\n        onProgress = callback;\n        progressReport = REPORT_INTERVAL;\n\n        if (length < 1) {\n            source.close();\n            throw new IOException(\"The chunk is empty or invalid\");\n        }\n        if (source.length() < end) {\n            try {\n                throw new IOException(String.format(\"invalid file length. expected = %s  found = %s\", end, source.length()));\n            } finally {\n                source.close();\n            }\n        }\n\n        source.seek(offset);\n    }\n\n    /**\n     * Get absolute position on file\n     *\n     * @return the position\n     */\n    public long getFilePointer() {\n        return offset + position;\n    }\n\n    @Override","sourceCodeStart":14,"sourceCodeEnd":50,"githubUrl":"https://github.com/TeamNewPipe/NewPipe/blob/9e8be091560a69f35d44bd252eb00bc7911c977b/app/src/main/java/us/shandian/giga/io/ChunkFileInputStream.java#L14-L50","documentation":"Thrown by ChunkFileInputStream when the underlying source stream is shorter than the requested chunk end offset: source.length() < end. The chunk declares it will read up to 'end' but the file is not that long, so reading would hit EOF prematurely. The constructor closes the source (in a finally block) and throws an IOException with the expected vs found lengths.","triggerScenarios":"new ChunkFileInputStream(target, start, end, callback) where source.length() < end. Caused by the file being truncated (download incomplete), a Content-Length/Content-Range mismatch where the server lied about the size, or stale size metadata used to compute chunk bounds.","commonSituations":"Resuming an interrupted download where the partial file is shorter than recorded; the server returned a different (smaller) file than expected; the file was deleted or truncated between size-discovery and chunk-read; mismatch between declared file size and actual bytes on disk.","solutions":["Verify source.length() >= end before constructing the stream (the same check the constructor does, done earlier with a clearer error).","Re-download the file from scratch if the on-disk size does not match the expected total size.","After an interrupted download, re-stat the file and recompute chunk bounds against the actual length.","Validate the server's Content-Length against the range request before allocating chunks."],"exampleFix":"// before\nnew ChunkFileInputStream(stream, start, end, callback);\n\n// after — guard against truncation\nif (stream.length() < end) {\n    throw new IOException(\"File truncated: need \" + end + \" bytes, have \" + stream.length());\n}\nnew ChunkFileInputStream(stream, start, end, callback);","handlingStrategy":"validation","validationCode":"// Verify source length covers the chunk end before constructing:\nif (source.length() < end) {\n    throw new IOException(\"Source truncated: need offset \" + end + \", have \" + source.length());\n}","typeGuard":null,"tryCatchPattern":"try {\n    ChunkFileInputStream in = new ChunkFileInputStream(stream, start, end, callback);\n} catch (IOException e) {\n    if (e.getMessage() != null && e.getMessage().startsWith(\"invalid file length\")) {\n        // file truncated — re-download from scratch\n        triggerFullRedownload();\n    } else throw e;\n}","preventionTips":["Re-stat the file and recompute chunk bounds against actual on-disk size when resuming.","Verify server Content-Length matches before allocating chunk offsets.","Treat a truncated source as requiring a full re-download, not a partial resume."],"tags":["io","download","chunking","byte-range","truncated-file"],"backgroundTag":null,"analyzedSha":"9e8be091560a69f35d44bd252eb00bc7911c977b","analyzedAt":"2026-08-14T00:11:33.519Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}