SubtitleEdit/subtitleedit · error · InvalidOperationException
No VobSub subtitles in MKV track #{track.TrackNumber}.
Error message
No VobSub subtitles in MKV track #{track.TrackNumber}. What it means
Thrown by BitmapSubtitleLoader.LoadMatroskaVobSub after every VobSub pack decoded from an MKV track produced a null bitmap (each incremented the 'skipped' counter). The packs exist and carry timing, but no renderable image plane could be produced — typically because the track's CodecPrivate lacks the VobSub .idx palette/CLUT lines or the subpicture RLE data is corrupt. It is a terminal guard: a track that yields zero bitmaps cannot be OCR'd or exported as images.
Source
Thrown at src/seconv/Core/BitmapSubtitleLoader.cs:238
continue;
}
// Use the block-derived Start/End (TimeSpan), not StartTimeCode/EndTimeCode which
// are based on the SubPicture delay and only correct for .sub+.idx sources.
// Screen size comes from the CodecPrivate "size:" line so an image output
// (e.g. bluraysup) keeps the DVD frame instead of defaulting to 1920x1080.
var position = pack.GetPosition();
items.Add(new BitmapSubtitleItem(
new TimeCode(pack.StartTime.TotalMilliseconds),
new TimeCode(pack.EndTime.TotalMilliseconds),
bmp,
screenWidth,
screenHeight,
new SKPointI(position.Left, position.Top)));
}
WarnSkippedBitmaps(skipped, "MKV VobSub");
if (items.Count == 0)
{
throw new InvalidOperationException($"No VobSub subtitles in MKV track #{track.TrackNumber}.");
}
return items;
}
/// <summary>
/// Video frame size from a Matroska VobSub track's CodecPrivate .idx text ("size: 720x576"),
/// or the DVD PAL default when the line is missing or malformed.
/// </summary>
internal static (int Width, int Height) GetVobSubIdxScreenSize(string? codecPrivate)
{
return TryGetVobSubIdxScreenSize(codecPrivate) ?? (720, 576);
}
/// <summary>
/// Frame size from .idx text ("size: 720x576"), or null when it carries no usable
/// <c>size:</c> line — the caller then picks its own default (DVD PAL vs NTSC differ,
/// so there is no single right fallback here).
/// </summary>View on GitHub (pinned to 17a9f07487)
Solutions
- Inspect the track with ffprobe/mkvinfo to confirm it actually contains VobSub subpicture data and check its CodecPrivate for 'palette:' and 'size:' lines.
- If the palette is missing, remux the source with mkvmerge from the original DVD/.sub+.idx so the CodecPrivate carries the CLUT.
- If the track is genuinely empty/corrupt, mux from the original VobSub (.sub+.idx) source or pick a different track.
- Catch the InvalidOperationException in the caller and skip the track with a warning, continuing with other tracks.
Example fix
// before
foreach (var track in subtitleTracks)
items = BitmapSubtitleLoader.LoadMatroskaVobSub(matroska, track, options);
// after
foreach (var track in subtitleTracks)
{
try { items = BitmapSubtitleLoader.LoadMatroskaVobSub(matroska, track, options); }
catch (InvalidOperationException ex) { AnsiConsole.MarkupLine($"[yellow]Skipping track #{track.TrackNumber}: {ex.Message}[/]"); continue; }
} Defensive patterns
Strategy: validation
Validate before calling
// Before loading, confirm the track has VobSub data and a palette in CodecPrivate.
var cp = track.GetCodecPrivate();
if (track.CodecId != "S_VOBSUB" || string.IsNullOrWhiteSpace(cp) || !cp.Contains("palette:"))
{
AnsiConsole.MarkupLine($"[yellow]Skipping track #{track.TrackNumber}: no VobSub palette in CodecPrivate.[/]");
continue;
} Try / catch
try { items = BitmapSubtitleLoader.LoadMatroskaVobSub(matroska, track, options); }
catch (InvalidOperationException ex) { AnsiConsole.MarkupLine($"[yellow]Skipping track #{track.TrackNumber}: {ex.Message.EscapeMarkup()}[/]"); continue; } Prevention
- Validate the Matroska track CodecId is S_VOBSUB and CodecPrivate contains 'palette:'/'size:' before calling LoadMatroskaVobSub.
- Catch InvalidOperationException per-track and continue with remaining tracks instead of failing the whole job.
- Pre-mux VobSub sources with mkvmerge so the CodecPrivate carries the full .idx metadata.
When it happens
Trigger: Calling LoadMatroskaVobSub(matroska, track, options) on a track where track.GetCodecPrivate() contains no 'palette:'/'size:' lines, so SubPicture.GetBitmap renders fully-transparent planes that GetBitmap() rejects; or where the VobSub block payloads are zero-length/malformed. Every iteration hits the 'if (bmp is null) { skipped++; continue; }' branch at BitmapSubtitleLoader.cs:217 and items stays empty at line 236.
Common situations: An MKV muxed by an old/broken tool that omitted the CodecPrivate idx text; a track that is an empty placeholder; a track whose subpicture data was truncated during a remux; a VobSub track compressed with content encoding 1 (a separate error is thrown earlier at line 183, but corrupted data downstream looks similar).
Related errors
- No VobSub subpictures found in MP4 track.
- No subtitle tracks in Matroska file: {filePath}
- No PGS subtitles in MKV track #{track.TrackNumber}.
- Unable to access bitmap pixel data.
- VobSub MKV track #{track.TrackNumber} is compressed (content
AI-assisted analysis of SubtitleEdit/subtitleedit@17a9f07487 (2026-08-13).
Data as JSON: /api/errors/e4c174a72dd2a944.
Report an issue: GitHub.