nilaoda/N_m3u8DL-RE · error · Exception
A TFHD box should have a valid flags value
Error message
A TFHD box should have a valid flags value
What it means
ExtractSub's 'tfhd' FullBox handler demands a valid flags value before calling MP4Parser.ParseTFHD; the sentinel 1000 is used by the parser to signal 'flags could not be read'. Receiving it means the Track Fragment Header box is malformed or was misparsed, so default sample duration/description info cannot be trusted.
Solutions
- Re-download the affected media segment; corruption is the most common cause.
- Verify the fragments really are MP4/fMP4 (not TS or another container) before feeding them to ExtractSub.
- Dump the fragment with MP4Box/Bento4 to inspect the tfhd box structure.
- Catch the exception and skip the broken fragment instead of aborting subtitle extraction.
Example fix
// before
var sub = MP4VttUtil.ExtractSub(segmentFiles, timescale); // throws on bad tfhd
// after
try
{
var sub = MP4VttUtil.ExtractSub(segmentFiles, timescale);
}
catch (Exception ex) when (ex.Message.Contains("TFHD box should have a valid flags"))
{
Log.Warning("Fragment has malformed tfhd box; skipping it");
} Defensive patterns
Strategy: try-catch
Try / catch
try { var sub = MP4VttUtil.ExtractSub(files, ts); }
catch (Exception ex) when (ex.Message.Contains("TFHD box should have a valid flags"))
{ Log.Warning("Fragment has malformed tfhd; skipping"); } Prevention
- Verify fragment integrity (container sniffing) before feeding to the MP4 parser.
- Do not pass non-MP4 containers (TS/WebM) to MP4VttUtil.
- Skip-and-log per fragment so a single malformed box doesn't abort extraction.
When it happens
Trigger: Calling ExtractSub on a media segment whose moof/traf/tfhd box reports Flags == 1000 (the parser's 'invalid/absent flags' sentinel), i.e. the tfhd box is too short, corrupt, or misaligned.
Common situations: Corrupt/truncated media fragment, bytes misinterpreted as fMP4 (e.g. a TS or WebM chunk fed to the MP4 parser), or a muxer writing nonstandard tfhd boxes.
Understand the failure class
Background: "unknown output mode", "invalid value for flag", "expects true/false": fixing invalid flag value errors in CLI tools — this error's family across 24 libraries.
Related errors
- TFDT version can only be 0 or 1
- MDHD version can only be 0 or 1
- Bad vtt!
- PSSH version can only be 0 or 1
- Mp4 box names must be 4 characters long
AI-assisted analysis of nilaoda/N_m3u8DL-RE@e113dee70c (2026-09-13).
Data as JSON: /api/errors/5c5e0e80af55bc1d.
Report an issue: GitHub.
Appendix: source
Thrown at src/N_m3u8DL-RE.Parser/Mp4/MP4VttUtil.cs:70
ulong defaultDuration = 0;
List<Sample> presentations = [];
// parse media
new MP4Parser()
.Box("moof", MP4Parser.Children)
.Box("traf", MP4Parser.Children)
.FullBox("tfdt", box =>
{
sawTFDT = true;
if (box.Version is not (0 or 1))
throw new Exception("TFDT version can only be 0 or 1");
baseTime = MP4Parser.ParseTFDT(box.Reader, box.Version);
})
.FullBox("tfhd", box =>
{
if (box.Flags == 1000)
throw new Exception("A TFHD box should have a valid flags value");
defaultDuration = MP4Parser.ParseTFHD(box.Reader, box.Flags).DefaultSampleDuration;
})
.FullBox("trun", box =>
{
sawTRUN = true;
if (box.Version == 1000)
throw new Exception("A TRUN box should have a valid version value");
if (box.Flags == 1000)
throw new Exception("A TRUN box should have a valid flags value");
presentations = MP4Parser.ParseTRUN(box.Reader, box.Version, box.Flags).SampleData;
})
.Box("mdat", MP4Parser.AllData(data =>
{
if (sawMDAT)
throw new Exception("VTT cues in mp4 with multiple MDAT are not currently supported");
sawMDAT = true;
rawPayload = data;
}))View on GitHub (pinned to e113dee70c)