SubtitleEdit/subtitleedit · error · InvalidOperationException

Could not find a free output filename for: {baseName}

Error message

Could not find a free output filename for: {baseName}

What it means

Thrown by ResolveOutputFileName when 9998 candidate filenames (stem_2 .. stem_9999) all already exist in the output directory and --overwrite is not set. The de-duplication loop is exhausted; the converter gives up rather than looping forever.

Source

Thrown at src/seconv/Core/SubtitleConverter.cs:846

        if (trackNumber.HasValue && !string.IsNullOrEmpty(languageSuffix))
        {
            var fileName = Path.GetFileNameWithoutExtension(inputFile);
            var withTrack = Path.Combine(dir, $"{fileName}.#{trackNumber.Value}.{languageSuffix}{ext}");
            if (!File.Exists(withTrack))
            {
                return withTrack;
            }
        }

        for (var i = 2; i < 10_000; i++)
        {
            var candidate = Path.Combine(dir, $"{stem}_{i}{ext}");
            if (!File.Exists(candidate))
            {
                return candidate;
            }
        }
        throw new InvalidOperationException($"Could not find a free output filename for: {baseName}");
    }
}

internal record class ConversionOptions
{
    public required IReadOnlyList<string> Patterns { get; init; }
    public required string Format { get; init; }
    public string? InputFolder { get; init; }
    public string? OutputFolder { get; init; }
    public string? OutputFilename { get; init; }
    public string? Encoding { get; init; }

    /// <summary>
    /// Encoding to assume when input has no BOM and is not detected as UTF-8.
    /// Replaces the ANSI codepage heuristic only — BOM and valid UTF-8 still win.
    /// Ignored when <see cref="Encoding"/> is set (which already forces input encoding).
    /// </summary>
    public string? InputEncodingFallback { get; init; }

View on GitHub (pinned to 17a9f07487)

Solutions

  1. Pass --overwrite to reuse the base name.
  2. Move or clean the output directory so candidates are free.
  3. Use a distinct --output-folder per run, or a more specific --output-filename.

Example fix

// before
seconv in.srt srt --output-folder ./out   // ./out already has in_2..in_9999.srt
// after
seconv in.srt srt --output-folder ./out --overwrite
Defensive patterns

Strategy: validation

Validate before calling

// Detect near-exhaustion before running
var dir = Path.GetDirectoryName(baseName) ?? ".";
var stem = Path.GetFileNameWithoutExtension(baseName);
var free = Enumerable.Range(2, 9998).Select(i => Path.Combine(dir, $"{stem}_{i}{ext}")).FirstOrDefault(p => !File.Exists(p));
if (free is null) throw new ArgException("Output directory is saturated; pass --overwrite or clean it.");

Type guard

null

Try / catch

null

Prevention

When it happens

Trigger: Output base name already exists, options.Overwrite is false, the track-number/language-suffixed variant also exists, and every stem_{i} for i in [2,9999] exists too.

Common situations: Running the same conversion thousands of times into one directory without --overwrite; a buggy script that loops conversions into a fixed folder; a directory seeded with auto-named files blocking all slots.

Related errors


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