nilaoda/N_m3u8DL-RE · error · Exception

MDHD version can only be 0 or 1

Error message

MDHD version can only be 0 or 1

What it means

MP4VttUtil.CheckInit builds an MP4Parser walk over the init segment and its 'mdhd' FullBox handler requires the mdhd version to be 0 or 1 (the only versions defined by ISO BMFF). Any other version byte indicates a corrupt or nonstandard track header, so CheckInit throws before a timescale can be read.

Solutions

  1. Re-download or re-mux the init segment; the file data is likely corrupt.
  2. Verify the file with MP4Box/Bento4 to inspect the mdhd box version.
  3. Ensure you are passing the correct init segment bytes (not media data or a shifted offset) to CheckInit.
  4. Catch the exception and report that the subtitle track init data is invalid.

Example fix

// before
var (sawWvtt, timescale) = MP4VttUtil.CheckInit(initBytes);

// after
try
{
    var (sawWvtt, timescale) = MP4VttUtil.CheckInit(initBytes);
}
catch (Exception ex) when (ex.Message.Contains("MDHD version"))
{
    throw new Exception("Subtitle init segment is corrupt (invalid mdhd box)");
}
Defensive patterns

Strategy: try-catch

Try / catch

try { var (sawWvtt, ts) = MP4VttUtil.CheckInit(initBytes); }
catch (Exception ex) when (ex.Message.Contains("MDHD version"))
{ throw new InvalidDataException("Init segment mdhd box is corrupt"); }

Prevention

When it happens

Trigger: Calling CheckInit on an MP4 init/segment whose moov/trak/mdia/mdhd full box has a version other than 0 or 1.

Common situations: Corrupt or truncated fMP4 init segment, a broken muxer emitting malformed mdhd boxes, or parsing a file that is not actually an MP4 (bytes misread shift the version field).

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


AI-assisted analysis of nilaoda/N_m3u8DL-RE@e113dee70c (2026-09-13). Data as JSON: /api/errors/35d72d62c6dff145. Report an issue: GitHub.

Appendix: source

Thrown at src/N_m3u8DL-RE.Parser/Mp4/MP4VttUtil.cs:21

namespace Mp4SubtitleParser;

public static class MP4VttUtil
{
    public static (bool, uint) CheckInit(byte[] data)
    {
        uint timescale = 0;
        bool sawWVTT = false;

        // parse init
        new MP4Parser()
            .Box("moov", MP4Parser.Children)
            .Box("trak", MP4Parser.Children)
            .Box("mdia", MP4Parser.Children)
            .FullBox("mdhd", box =>
            {
                if (box.Version is not (0 or 1))
                    throw new Exception("MDHD version can only be 0 or 1");
                timescale = MP4Parser.ParseMDHD(box.Reader, box.Version);
            })
            .Box("minf", MP4Parser.Children)
            .Box("stbl", MP4Parser.Children)
            .FullBox("stsd", MP4Parser.SampleDescription)
            .Box("wvtt", _ => {
                // A valid vtt init segment, though we have no actual subtitles yet.
                sawWVTT = true;
            })
            .Parse(data);

        return (sawWVTT, timescale);
    }

    public static WebVttSub ExtractSub(IEnumerable<string> files, uint timescale)
    {
        if (timescale == 0)
            throw new Exception("Missing timescale for VTT content!");

View on GitHub (pinned to e113dee70c)