{"record":{"id":"3e30ac874658dca0","repo":"TeamNewPipe/NewPipe","slug":"eof-reached-in-box-type-s-offset-s-size-s","errorCode":null,"errorMessage":"EOF reached in box: type=%s offset=%s size=%s","messagePattern":"EOF reached in box: type=(.+?) offset=(.+?) size=(.+?)","errorType":"exception","errorClass":"EOFException","httpStatus":null,"severity":"error","filePath":"app/src/main/java/org/schabi/newpipe/streams/Mp4DashReader.java","lineNumber":298,"sourceCode":"        if (b.type != expected) {\n            throw new NoSuchElementException(\"expected \" + boxName(expected)\n                    + \" found \" + boxName(b));\n        }\n        return b;\n    }\n\n    private byte[] readFullBox(final Box ref) throws IOException {\n        // full box reading is limited to 2 GiB, and should be enough\n        final int size = (int) ref.size;\n\n        final ByteBuffer buffer = ByteBuffer.allocate(size);\n        buffer.putInt(size);\n        buffer.putInt(ref.type);\n\n        final int read = size - 8;\n\n        if (stream.read(buffer.array(), 8, read) != read) {\n            throw new EOFException(String.format(\"EOF reached in box: type=%s offset=%s size=%s\",\n                    boxName(ref.type), ref.offset, ref.size));\n        }\n\n        return buffer.array();\n    }\n\n    private void ensure(final Box ref) throws IOException {\n        final long skip = ref.offset + ref.size - stream.position();\n\n        if (skip == 0) {\n            return;\n        } else if (skip < 0) {\n            throw new EOFException(String.format(\n                    \"parser go beyond limits of the box. type=%s offset=%s size=%s position=%s\",\n                    boxName(ref), ref.offset, ref.size, stream.position()\n            ));\n        }\n","sourceCodeStart":280,"sourceCodeEnd":316,"githubUrl":"https://github.com/TeamNewPipe/NewPipe/blob/9e8be091560a69f35d44bd252eb00bc7911c977b/app/src/main/java/org/schabi/newpipe/streams/Mp4DashReader.java#L280-L316","documentation":"Mp4DashReader.readFullBox allocates a ByteBuffer for the declared box size and reads (size - 8) bytes after the 8-byte header. If stream.read returns fewer bytes than requested, the box content is incomplete and an EOFException with type/offset/size is thrown. It guards against a box header claiming a size larger than what the stream can deliver.","triggerScenarios":"Reading any full box (mvhd, tkhd, tfhd, trun, etc.) whose declared size exceeds the remaining bytes in the stream. The header was read successfully but the body was truncated.","commonSituations":"A download cut off mid-box; a box size field corrupted to an inflated value; a server that closed the connection after sending headers; a cached file partially written.","solutions":["Re-download the file; the box body is incomplete.","Validate the file's total length against the sum of declared box sizes before parsing deep structures.","Check the download completed (HTTP 200, full Content-Length received) before demuxing.","Catch EOFException and surface a 'media incomplete' error to the user."],"exampleFix":"// no caller-side fix for a truncated box; guard at the download boundary\n// before\nSharpStream s = download(url); // may be truncated\nreader.parse();\n\n// after — assert full download before parsing\nif (downloadedBytes != response.contentLength()) {\n    throw new IOException(\"incomplete download\");\n}\nreader.parse();","handlingStrategy":"validation","validationCode":"// Verify the stream length covers the largest declared box size before deep parsing.\nif (source.isLengthKnown() && source.length() < firstBoxSize) {\n    throw new IOException(\"source shorter than declared first box size\");\n}","typeGuard":"// Wrap the stream to fail fast on short reads at the box boundary.\npublic static boolean canReadFullBox(SharpStream s, long boxSize) {\n    return s.isLengthKnown() && (s.length() - s.position()) >= boxSize;\n}","tryCatchPattern":"try {\n    byte[] body = readFullBox(boxRef);\n} catch (EOFException e) {\n    // box body truncated — file is incomplete, do not retry\n    throw new IOException(\"incomplete MP4 box at offset \" + boxRef.offset, e);\n}","preventionTips":["Confirm downloads completed (full Content-Length) before parsing.","Reject sources whose length is unknown when strict box sizes are required.","Validate total file length against declared box sizes up front.","Surface a 'media incomplete' error rather than crashing on EOF."],"tags":["mp4","io","truncated-data","container","java"],"backgroundTag":null,"analyzedSha":"9e8be091560a69f35d44bd252eb00bc7911c977b","analyzedAt":"2026-08-14T00:11:33.519Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}