TeamNewPipe/NewPipe · warning · EOFException

EOF reached while reading a sample

Error message

EOF reached while reading a sample

What it means

Mp4DashReader.Mp4DashChunk.nextSample() allocates a byte[] sized to sample.info.sampleSize and reads that many bytes from the chunk data. If data.read() returns fewer bytes than sampleSize, the sample is incomplete and an EOFException is thrown. This protects against a chunk whose mdat payload is shorter than the sample table declares.

Source

Thrown at app/src/main/java/org/schabi/newpipe/streams/Mp4DashReader.java:932

                return null;
            }
            return moof.traf.trun.getAbsoluteEntry(i++, moof.traf.tfhd);
        }

        public Mp4DashSample getNextSample() throws IOException {
            if (data == null) {
                throw new IllegalStateException("This chunk has info only");
            }
            if (i >= moof.traf.trun.entryCount) {
                return null;
            }

            final Mp4DashSample sample = new Mp4DashSample();
            sample.info = moof.traf.trun.getAbsoluteEntry(i++, moof.traf.tfhd);
            sample.data = new byte[sample.info.sampleSize];

            if (data.read(sample.data) != sample.info.sampleSize) {
                throw new EOFException("EOF reached while reading a sample");
            }

            return sample;
        }
    }

    public static class Mp4DashSample {
        public TrunEntry info;
        public byte[] data;
    }
}

View on GitHub (pinned to 9e8be09156)

Solutions

  1. Re-download the segment; the mdat payload is shorter than the sample table.
  2. Verify the moof+mdat pair is fully downloaded before iterating samples.
  3. Catch EOFException during sample iteration and stop gracefully (partial audio extraction may still be usable).
  4. If muxing, ensure each trun sample size sums exactly to the mdat content length.

Example fix

// before
while ((sample = chunk.nextSample()) != null) { write(sample); } // throws on last sample

// after — tolerate truncation on the final sample
try {
    while ((sample = chunk.nextSample()) != null) { write(sample); }
} catch (EOFException e) {
    Log.w(TAG, "chunk truncated at final sample: " + e.getMessage());
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Before iterating samples, confirm the chunk's mdat covers the declared sample sizes.
long declared = 0;
for (int i = 0; i < chunk.moof.traf.trun.entryCount; i++)
    declared += chunk.moof.traf.trun.getAbsoluteEntry(i, chunk.moof.traf.tfhd).sampleSize;
if (declared > chunk.data.available()) {
    throw new IOException("mdat shorter than declared sample sizes");
}

Type guard

public static boolean chunkPayloadComplete(Mp4DashChunk chunk, long declaredBytes) {
    return chunk.data != null && chunk.data.available() >= declaredBytes;
}

Try / catch

try {
    while ((sample = chunk.nextSample()) != null) { write(sample.data); }
} catch (EOFException e) {
    // last sample truncated — keep already-extracted samples, stop gracefully
    Log.w(TAG, "chunk ended early: " + e.getMessage());
}

Prevention

When it happens

Trigger: Iterating samples via nextSample() when the mdat payload for the current chunk contains fewer bytes than the trun sample table claims (sampleSize per entry). A truncated mdat or an over-declared sample size.

Common situations: A truncated media segment download; a moof whose trun sample sizes don't match the mdat length; a re-encoded stream whose segment boundaries shifted; a partial download resumed from the wrong offset.

Related errors


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