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

  1. Inspect the track with ffprobe/mkvinfo to confirm it actually contains VobSub subpicture data and check its CodecPrivate for 'palette:' and 'size:' lines.
  2. If the palette is missing, remux the source with mkvmerge from the original DVD/.sub+.idx so the CodecPrivate carries the CLUT.
  3. If the track is genuinely empty/corrupt, mux from the original VobSub (.sub+.idx) source or pick a different track.
  4. 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

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


AI-assisted analysis of SubtitleEdit/subtitleedit@17a9f07487 (2026-08-13). Data as JSON: /api/errors/e4c174a72dd2a944. Report an issue: GitHub.