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

  1. Re-download the segment; the trun header is internally inconsistent and cannot be trusted.
  2. Re-mux with a conformant MP4 muxer to regenerate correct trun data offsets.
  3. Validate fragments with an MP4 conformance tool before demuxing.
  4. 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

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


AI-assisted analysis of TeamNewPipe/NewPipe@9e8be09156 (2026-08-14). Data as JSON: /api/errors/ee5fe548786e4bf5. Report an issue: GitHub.