TeamNewPipe/NewPipe · error · IOException
trun box has wrong data offset, points outside of concurrent
Error message
trun box has wrong data offset, points outside of concurrent mdat box
What it means
In nextChunk(), after parsing a moof the reader adjusts trun.dataOffset by subtracting (box.size + 8) to convert it into a relative offset. If the result is negative, the trun's declared data offset points before the start of the current mdat — an impossible/invalid value. The IOException catches malformed or maliciously crafted fragment headers that would misdirect sample reads.
Source
Thrown at app/src/main/java/org/schabi/newpipe/streams/Mp4DashReader.java:204
box = readBox();
} else {
chunkZero = true;
}
switch (box.type) {
case ATOM_MOOF:
if (moof != null) {
throw new IOException("moof found without mdat");
}
moof = parseMoof(box, track.trak.tkhd.trackId);
if (moof.traf != null) {
if (hasFlag(moof.traf.trun.bFlags, 0x0001)) {
moof.traf.trun.dataOffset -= box.size + 8;
if (moof.traf.trun.dataOffset < 0) {
throw new IOException("trun box has wrong data offset, "
+ "points outside of concurrent mdat box");
}
}
if (moof.traf.trun.chunkSize < 1) {
if (hasFlag(moof.traf.tfhd.bFlags, 0x10)) {
moof.traf.trun.chunkSize = moof.traf.tfhd.defaultSampleSize
* moof.traf.trun.entryCount;
} else {
moof.traf.trun.chunkSize = (int) (box.size - 8);
}
}
if (!hasFlag(moof.traf.trun.bFlags, 0x900)
&& moof.traf.trun.chunkDuration == 0) {
if (hasFlag(moof.traf.tfhd.bFlags, 0x20)) {
moof.traf.trun.chunkDuration = moof.traf.tfhd.defaultSampleDuration
* moof.traf.trun.entryCount;
}View on GitHub (pinned to 9e8be09156)
Solutions
- Re-download the segment; the trun header is internally inconsistent and cannot be trusted.
- Re-mux with a conformant MP4 muxer to regenerate correct trun data offsets.
- Validate fragments with an MP4 conformance tool before demuxing.
- If you control muxing, ensure trun.dataOffset is set to the absolute position of the first sample relative to the file, never to a value smaller than the moof header extent.
Example fix
// before — muxer writes raw trun.dataOffset without accounting for box header trun.dataOffset = samplesStart; // after — set absolute offset from start of file (moof header size included) trun.dataOffset = moofFileOffset + moofHeaderSize + samplesStart;
Defensive patterns
Strategy: validation
Validate before calling
// Validate the trun dataOffset is internally consistent before relying on it. // This is a producer-side check; consumers cannot repair a bad offset. // When muxing: ensure trun.dataOffset >= (moofBoxSize + 8).
Type guard
public static boolean trunDataOffsetValid(long dataOffset, long moofBoxSize) {
return (dataOffset - (moofBoxSize + 8)) >= 0;
} Try / catch
try {
chunk = reader.getNextChunk(false);
} catch (IOException e) {
if (e.getMessage().contains("data offset")) {
// fragment has an invalid trun offset — skip this fragment, try the next
Log.w(TAG, "bad trun offset, skipping fragment");
continue;
} else throw e;
} Prevention
- Re-download fragments whose trun offsets are inconsistent.
- When muxing, compute trun.dataOffset as an absolute file position.
- Validate fragments with MP4Box conformance checks.
- Do not trust hand-edited MP4 files.
When it happens
Trigger: A moof whose trun box has the data-offset-present flag (0x0001) set but whose dataOffset value is smaller than (moof box size + 8), yielding a negative relative offset. Caused by a corrupt or hand-crafted trun box.
Common situations: A malformed fragment produced by a broken server-side packager; a file edited/tampered with; a partial download that corrupted the trun header fields.
Related errors
- moof found without mdat
- mdat found without moof
- parser go beyond limits of the box. type=%s offset=%s size=%
- Not a MPEG-4 DASH container, major brand is not 'dash' or 'i
- The provided Mp4 doesn't have the 'moov' box
AI-assisted analysis of TeamNewPipe/NewPipe@9e8be09156 (2026-08-14).
Data as JSON: /api/errors/ee5fe548786e4bf5.
Report an issue: GitHub.