{"record":{"id":"e4c174a72dd2a944","repo":"SubtitleEdit/subtitleedit","slug":"no-vobsub-subtitles-in-mkv-track-track-tracknumb","errorCode":null,"errorMessage":"No VobSub subtitles in MKV track #{track.TrackNumber}.","messagePattern":"No VobSub subtitles in MKV track #(.+?)\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/seconv/Core/BitmapSubtitleLoader.cs","lineNumber":238,"sourceCode":"                continue;\n            }\n            // Use the block-derived Start/End (TimeSpan), not StartTimeCode/EndTimeCode which\n            // are based on the SubPicture delay and only correct for .sub+.idx sources.\n            // Screen size comes from the CodecPrivate \"size:\" line so an image output\n            // (e.g. bluraysup) keeps the DVD frame instead of defaulting to 1920x1080.\n            var position = pack.GetPosition();\n            items.Add(new BitmapSubtitleItem(\n                new TimeCode(pack.StartTime.TotalMilliseconds),\n                new TimeCode(pack.EndTime.TotalMilliseconds),\n                bmp,\n                screenWidth,\n                screenHeight,\n                new SKPointI(position.Left, position.Top)));\n        }\n        WarnSkippedBitmaps(skipped, \"MKV VobSub\");\n        if (items.Count == 0)\n        {\n            throw new InvalidOperationException($\"No VobSub subtitles in MKV track #{track.TrackNumber}.\");\n        }\n        return items;\n    }\n\n    /// <summary>\n    /// Video frame size from a Matroska VobSub track's CodecPrivate .idx text (\"size: 720x576\"),\n    /// or the DVD PAL default when the line is missing or malformed.\n    /// </summary>\n    internal static (int Width, int Height) GetVobSubIdxScreenSize(string? codecPrivate)\n    {\n        return TryGetVobSubIdxScreenSize(codecPrivate) ?? (720, 576);\n    }\n\n    /// <summary>\n    /// Frame size from .idx text (\"size: 720x576\"), or null when it carries no usable\n    /// <c>size:</c> line — the caller then picks its own default (DVD PAL vs NTSC differ,\n    /// so there is no single right fallback here).\n    /// </summary>","sourceCodeStart":220,"sourceCodeEnd":256,"githubUrl":"https://github.com/SubtitleEdit/subtitleedit/blob/17a9f0748781032255db3526b7215d2fb891e3af/src/seconv/Core/BitmapSubtitleLoader.cs#L220-L256","documentation":"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.","triggerScenarios":"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.","commonSituations":"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).","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."],"exampleFix":"// before\nforeach (var track in subtitleTracks)\n    items = BitmapSubtitleLoader.LoadMatroskaVobSub(matroska, track, options);\n\n// after\nforeach (var track in subtitleTracks)\n{\n    try { items = BitmapSubtitleLoader.LoadMatroskaVobSub(matroska, track, options); }\n    catch (InvalidOperationException ex) { AnsiConsole.MarkupLine($\"[yellow]Skipping track #{track.TrackNumber}: {ex.Message}[/]\"); continue; }\n}","handlingStrategy":"validation","validationCode":"// Before loading, confirm the track has VobSub data and a palette in CodecPrivate.\nvar cp = track.GetCodecPrivate();\nif (track.CodecId != \"S_VOBSUB\" || string.IsNullOrWhiteSpace(cp) || !cp.Contains(\"palette:\"))\n{\n    AnsiConsole.MarkupLine($\"[yellow]Skipping track #{track.TrackNumber}: no VobSub palette in CodecPrivate.[/]\");\n    continue;\n}","typeGuard":null,"tryCatchPattern":"try { items = BitmapSubtitleLoader.LoadMatroskaVobSub(matroska, track, options); }\ncatch (InvalidOperationException ex) { AnsiConsole.MarkupLine($\"[yellow]Skipping track #{track.TrackNumber}: {ex.Message.EscapeMarkup()}[/]\"); continue; }","preventionTips":["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."],"tags":["vobsub","mkv","bitmap","subtitle","matroska"],"backgroundTag":null,"analyzedSha":"17a9f0748781032255db3526b7215d2fb891e3af","analyzedAt":"2026-08-13T18:11:43.374Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}