{"record":{"id":"24f86b8e7b902471","repo":"SubtitleEdit/subtitleedit","slug":"could-not-find-a-free-output-filename-for-basena","errorCode":null,"errorMessage":"Could not find a free output filename for: {baseName}","messagePattern":"Could not find a free output filename for: (.+?)","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/seconv/Core/SubtitleConverter.cs","lineNumber":846,"sourceCode":"        if (trackNumber.HasValue && !string.IsNullOrEmpty(languageSuffix))\n        {\n            var fileName = Path.GetFileNameWithoutExtension(inputFile);\n            var withTrack = Path.Combine(dir, $\"{fileName}.#{trackNumber.Value}.{languageSuffix}{ext}\");\n            if (!File.Exists(withTrack))\n            {\n                return withTrack;\n            }\n        }\n\n        for (var i = 2; i < 10_000; i++)\n        {\n            var candidate = Path.Combine(dir, $\"{stem}_{i}{ext}\");\n            if (!File.Exists(candidate))\n            {\n                return candidate;\n            }\n        }\n        throw new InvalidOperationException($\"Could not find a free output filename for: {baseName}\");\n    }\n}\n\ninternal record class ConversionOptions\n{\n    public required IReadOnlyList<string> Patterns { get; init; }\n    public required string Format { get; init; }\n    public string? InputFolder { get; init; }\n    public string? OutputFolder { get; init; }\n    public string? OutputFilename { get; init; }\n    public string? Encoding { get; init; }\n\n    /// <summary>\n    /// Encoding to assume when input has no BOM and is not detected as UTF-8.\n    /// Replaces the ANSI codepage heuristic only — BOM and valid UTF-8 still win.\n    /// Ignored when <see cref=\"Encoding\"/> is set (which already forces input encoding).\n    /// </summary>\n    public string? InputEncodingFallback { get; init; }","sourceCodeStart":828,"sourceCodeEnd":864,"githubUrl":"https://github.com/SubtitleEdit/subtitleedit/blob/17a9f0748781032255db3526b7215d2fb891e3af/src/seconv/Core/SubtitleConverter.cs#L828-L864","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Pass --overwrite to reuse the base name.","Move or clean the output directory so candidates are free.","Use a distinct --output-folder per run, or a more specific --output-filename."],"exampleFix":"// before\nseconv in.srt srt --output-folder ./out   // ./out already has in_2..in_9999.srt\n// after\nseconv in.srt srt --output-folder ./out --overwrite","handlingStrategy":"validation","validationCode":"// Detect near-exhaustion before running\nvar dir = Path.GetDirectoryName(baseName) ?? \".\";\nvar stem = Path.GetFileNameWithoutExtension(baseName);\nvar free = Enumerable.Range(2, 9998).Select(i => Path.Combine(dir, $\"{stem}_{i}{ext}\")).FirstOrDefault(p => !File.Exists(p));\nif (free is null) throw new ArgException(\"Output directory is saturated; pass --overwrite or clean it.\");","typeGuard":"null","tryCatchPattern":"null","preventionTips":["Default to --overwrite in idempotent batch jobs.","Use a fresh --output-folder per run.","Periodically clean auto-named directories."],"tags":["seconv","filename-collision","filesystem","overwrite","cli-flags"],"backgroundTag":null,"analyzedSha":"17a9f0748781032255db3526b7215d2fb891e3af","analyzedAt":"2026-08-13T18:11:43.374Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}