SubtitleEdit/subtitleedit · error · InvalidOperationException

No VOB files supplied.

Error message

No VOB files supplied.

What it means

Thrown by VobSubExtractor.Extract when the vobFiles list is empty. The extractor needs at least one .VOB to parse, so an empty input is a caller bug (the CLI should not reach here with no files).

Source

Thrown at src/seconv/Core/VobSubExtractor.cs:38

/// </summary>
internal static class VobSubExtractor
{
    /// <summary>One output produced by a successful extraction.</summary>
    public sealed record StreamOutput(string Path, int StreamId, int Written);

    /// <summary>
    /// Parse <paramref name="vobFiles"/> (treated as one logical title) and write
    /// one .sub + .idx pair per discovered subpicture stream. <paramref name="subOutputPath"/>
    /// must already end in <c>.sub</c>; when there's more than one stream, the
    /// stream index is inserted before the extension (<c>movie.sub</c> →
    /// <c>movie.0.sub</c>, <c>movie.1.sub</c>, …) and the matching .idx is
    /// written alongside each one.
    /// </summary>
    public static IReadOnlyList<StreamOutput> Extract(IReadOnlyList<string> vobFiles, string subOutputPath, bool isPal)
    {
        if (vobFiles.Count == 0)
        {
            throw new InvalidOperationException("No VOB files supplied.");
        }

        if (!subOutputPath.EndsWith(".sub", StringComparison.OrdinalIgnoreCase))
        {
            // Guard: VobSubWriter derives the .idx path with a literal
            // Substring(0, Length - 3) + "idx" — pass anything other than ".sub"
            // here and the .idx ends up at the wrong path (e.g. movie → "vie"+"idx"
            // = "vieidx"). Caller normalises, but assert just in case.
            throw new ArgumentException("subOutputPath must end in '.sub'", nameof(subOutputPath));
        }

        // Parse every VOB into per-stream merged packs. DVDs assign continuous PTS
        // across VOB chunks of the same title, so packs from later VOBs naturally
        // land after earlier ones in playback time.
        var allPacks = new List<VobSubMergedPack>();
        foreach (var vob in vobFiles)
        {
            var parser = new VobSubParser(isPal);

View on GitHub (pinned to 17a9f07487)

Solutions

  1. Confirm the .VOB files exist and the glob/path list is non-empty before calling Extract.
  2. Pass explicit VTS_xx_1.VOB (and later) files — the subtitle-bearing chunks, not VTS_xx_0.VOB.
  3. Add a guard in the caller to report a clearer 'no input files' message.

Example fix

// before
VobSubExtractor.Extract(Array.Empty<string>(), outPath, isPal);
// after
if (vobFiles.Count == 0) throw new ArgumentException("Supply at least one .VOB file.");
VobSubExtractor.Extract(vobFiles, outPath, isPal);
Defensive patterns

Strategy: validation

Validate before calling

if (vobFiles is null || vobFiles.Count == 0)
    throw new ArgumentException("Supply at least one .VOB file.", nameof(vobFiles));

Type guard

static bool HasVobs(IReadOnlyList<string> f) => f is { Count: > 0 };

Try / catch

null

Prevention

When it happens

Trigger: VobSubExtractor.Extract is called with an IReadOnlyList<string> of length 0.

Common situations: A glob pattern that matched no VOB files was passed through to the extractor; the input list was built but filtered down to nothing; programmatic caller forgot to validate.

Related errors


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