SubtitleEdit/subtitleedit · error · InvalidOperationException

No VobSub subtitle packs in: {subPath}

Error message

No VobSub subtitle packs in: {subPath}

What it means

InvalidOperationException from LoadVobSub: VobSubParser.OpenSubIdx ran but MergeVobSubPacks returned zero subtitle packs. The .sub file parsed (no throw) but contained no usable SPUs. The .idx is optional (OpenSubIdx falls back to stream parsing), so its absence alone is not the cause.

Source

Thrown at src/seconv/Core/BitmapSubtitleLoader.cs:91

    /// VobSub <c>.sub</c> (+ optional <c>.idx</c>) → bitmap events. Uses
    /// <see cref="VobSubParser.OpenSubIdx"/>, which uses the .idx for timing + palette when
    /// present and otherwise parses the .sub's MPEG-PS stream directly (stream PTS timing +
    /// a default palette). The frame size comes from the .idx's <c>size:</c> line when it has
    /// one — VobSub is not always DVD-sized (Subtitle Edit's own export writes whatever the
    /// source was, e.g. <c>size: 1920x1080</c>) and squeezing a 1920x1080 stream into a DVD
    /// frame moves every subpicture. Without that line, fall back to the DVD standards
    /// (720x576 PAL, 720x480 NTSC) rather than <c>--resolution</c> / 1920x1080.
    /// </summary>
    public static IReadOnlyList<BitmapSubtitleItem> LoadVobSub(string subPath, string idxPath, bool isPal)
    {
        var parser = new VobSubParser(isPal);
        // OpenSubIdx falls back to parsing the .sub stream directly when the .idx is missing,
        // so an absent companion is not fatal — see IsBinaryVobSub for the caller's gate.
        parser.OpenSubIdx(subPath, idxPath);
        var packs = parser.MergeVobSubPacks();
        if (packs.Count == 0)
        {
            throw new InvalidOperationException($"No VobSub subtitle packs in: {subPath}");
        }

        var (screenWidth, screenHeight) = TryGetVobSubIdxScreenSize(ReadIdxText(idxPath))
                                          ?? (720, isPal ? 576 : 480);

        var items = new List<BitmapSubtitleItem>(packs.Count);
        var skipped = 0;
        foreach (var pack in packs)
        {
            // Without the .idx CLUT, SubPicture.GetBitmap skips both the SetColor and
            // SetContrast (per-plane alpha) display commands, so normally-transparent
            // outline/anti-alias planes render opaque and fuse into the glyphs — the
            // garbled OCR in issue #12772 ('-'→'=', 'S'→'$'). Mirrors the GUI, which
            // always passes VobSubParser.IdxPalette.
            if (parser.IdxPalette.Count > 0)
            {
                pack.Palette = parser.IdxPalette;
            }

View on GitHub (pinned to 17a9f07487)

Solutions

  1. Confirm the file is an MPEG-PS VobSub .sub (look for pack start codes 0x000001BA).
  2. Re-extract the VobSub from the source VOB/MKV (e.g. mkvextract tracks <file> <n>:out.sub).
  3. Provide the matching .idx alongside the .sub so timing/palette load correctly.

Example fix

// before
if (packs.Count == 0)
    throw new InvalidOperationException($"No VobSub subtitle packs in: {subPath}");

// after
if (packs.Count == 0)
    throw new InvalidOperationException($"No VobSub subtitle packs in '{subPath}'. File size: {new FileInfo(subPath).Length} bytes; idx present: {File.Exists(idxPath)}.");
Defensive patterns

Strategy: validation

Validate before calling

static bool LooksLikeVobSub(string path)
{
    if (!File.Exists(path)) return false;
    using var fs = File.OpenRead(path);
    var buf = new byte[4];
    if (fs.Read(buf, 0, 4) != 4) return false;
    return buf[0] == 0x00 && buf[1] == 0x00 && buf[2] == 0x01 && (buf[3] == 0xBA || buf[3] == 0xBD);
}

Type guard

static bool IsVobSubStream(string path) => LooksLikeVobSub(path);

Try / catch

null

Prevention

When it happens

Trigger: Pointing LoadVobSub at a .sub that is empty, truncated, or not an MPEG-PS VobSub stream; corrupt pack headers; or a .sub that is actually another format.

Common situations: Copied .sub without the .idx and the stream itself has no packs; demuxer wrote a zero-byte .sub; user passed an MKV-extracted .sub that uses a different container.

Related errors


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