{"record":{"id":"558f35439e179786","repo":"TeamNewPipe/NewPipe","slug":"moof-found-without-mdat","errorCode":null,"errorMessage":"moof found without mdat","messagePattern":"moof found without mdat","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"app/src/main/java/org/schabi/newpipe/streams/Mp4DashReader.java","lineNumber":194,"sourceCode":"    public Mp4DashChunk getNextChunk(final boolean infoOnly) throws IOException {\n        final Mp4Track track = tracks[selectedTrack];\n\n        while (stream.available()) {\n\n            if (chunkZero) {\n                ensure(box);\n                if (!stream.available()) {\n                    break;\n                }\n                box = readBox();\n            } else {\n                chunkZero = true;\n            }\n\n            switch (box.type) {\n                case ATOM_MOOF:\n                    if (moof != null) {\n                        throw new IOException(\"moof found without mdat\");\n                    }\n\n                    moof = parseMoof(box, track.trak.tkhd.trackId);\n\n                    if (moof.traf != null) {\n\n                        if (hasFlag(moof.traf.trun.bFlags, 0x0001)) {\n                            moof.traf.trun.dataOffset -= box.size + 8;\n                            if (moof.traf.trun.dataOffset < 0) {\n                                throw new IOException(\"trun box has wrong data offset, \"\n                                        + \"points outside of concurrent mdat box\");\n                            }\n                        }\n\n                        if (moof.traf.trun.chunkSize < 1) {\n                            if (hasFlag(moof.traf.tfhd.bFlags, 0x10)) {\n                                moof.traf.trun.chunkSize = moof.traf.tfhd.defaultSampleSize\n                                        * moof.traf.trun.entryCount;","sourceCodeStart":176,"sourceCodeEnd":212,"githubUrl":"https://github.com/TeamNewPipe/NewPipe/blob/9e8be091560a69f35d44bd252eb00bc7911c977b/app/src/main/java/org/schabi/newpipe/streams/Mp4DashReader.java#L176-L212","documentation":"During nextChunk(), a second moof (Movie Fragment) box is encountered while a previous moof is still pending (moof != null). In a well-formed fragmented MP4 each moof is immediately followed by its mdat; a second moof before the first's mdat means the structure is out of order or corrupt. The IOException signals the parser cannot reconcile the overlapping fragment headers.","triggerScenarios":"A fragmented MP4 where moof boxes appear consecutively without an intervening mdat; a corrupt/malformed segment; a file that was truncated or had boxes reordered by a faulty muxer.","commonSituations":"Corrupt download where mdat bytes were lost but moof headers survived; a buggy server-side fragmenter; manual concatenation of fragments that dropped mdat payloads.","solutions":["Re-download the source file; box ordering corruption is almost always a damaged transfer.","Re-mux the content with a known-good tool (ffmpeg/MP4Box) to fix the box layout.","Validate the file with mp4info/MP4Box -info before feeding it to the reader.","Catch IOException around nextChunk() and skip to the next valid fragment boundary if lossy recovery is acceptable."],"exampleFix":"// before\nwhile ((chunk = reader.getNextChunk(false)) != null) { ... } // throws mid-iteration\n\n// after — tolerate a single corrupt fragment and continue\ntry {\n    while ((chunk = reader.getNextChunk(false)) != null) { ... }\n} catch (IOException e) {\n    Log.w(TAG, \"fragment ordering broken, stopping at \" + e.getMessage());\n}","handlingStrategy":"try-catch","validationCode":"// No pre-check can predict interleaved box order without full parsing;\n// instead, validate file integrity with MP4Box before demuxing.\n// MP4Box -info file.mp4   (exit non-zero or reports errors ⇒ do not feed to reader)","typeGuard":"// Not expressible as a type guard; this is runtime structural corruption.\n// Use a boolean returned by a validation pass:\npublic static boolean boxOrderValid(Mp4DashReader r) { /* full scan */ return true; }","tryCatchPattern":"try {\n    while ((chunk = reader.getNextChunk(false)) != null) { process(chunk); }\n} catch (IOException e) {\n    if (e.getMessage().contains(\"moof found without mdat\")) {\n        Log.w(TAG, \"fragment ordering corrupt; stopping extraction here\");\n    } else throw e;\n}","preventionTips":["Validate the file with MP4Box/mp4info before demuxing.","Re-download suspect segments rather than parsing damaged data.","Do not manually reorder or edit MP4 boxes.","Treat box-ordering errors as fatal for the current fragment, not the whole file."],"tags":["mp4","dash","container","corrupt-data","java"],"backgroundTag":null,"analyzedSha":"9e8be091560a69f35d44bd252eb00bc7911c977b","analyzedAt":"2026-08-14T00:11:33.519Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}