{"record":{"id":"358a49aedc907120","repo":"SubtitleEdit/subtitleedit","slug":"multiple-replace-file-not-found-path","errorCode":null,"errorMessage":"Multiple-replace file not found: {path}","messagePattern":"Multiple-replace file not found: (.+?)","errorType":"exception","errorClass":"FileNotFoundException","httpStatus":null,"severity":"error","filePath":"src/seconv/Core/MultipleReplaceLoader.cs","lineNumber":392,"sourceCode":"            public string ReplaceWith { get; set; } = string.Empty;\n            public string? Description { get; set; }\n            public bool IsActive { get; set; }\n            public string Type { get; set; } = string.Empty;\n        }\n    }\n\n    /// <summary>\n    /// Loads + applies all active rules from <paramref name=\"path\"/> to <paramref name=\"subtitle\"/>.\n    /// The file may be the legacy SE4 <c>MultipleSearchAndReplaceGroups</c> XML, or the SE5\n    /// GUI's exported <c>.template</c> JSON or <c>.csv</c> (Tools &gt; Multiple replace &gt;\n    /// export). Format is chosen by extension, then by content sniffing. Returns the number of\n    /// paragraphs whose text was modified.\n    /// </summary>\n    public static int Apply(Subtitle subtitle, string path)\n    {\n        if (!File.Exists(path))\n        {\n            throw new FileNotFoundException($\"Multiple-replace file not found: {path}\", path);\n        }\n\n        var rules = LoadRules(path);\n        if (rules.Count == 0)\n        {\n            return 0;\n        }\n\n        // Pre-compile rule patterns once (not per-paragraph):\n        //  - RegularExpression rules use the user pattern with RegexOptions.Multiline so ^/$\n        //    anchors match at every line boundary, matching the UI (MultipleReplaceViewModel\n        //    compiles with Compiled | Multiline).\n        //  - Normal (case-insensitive literal) rules compile an escaped, IgnoreCase pattern\n        //    so the per-paragraph loop no longer re-escapes and re-parses on every line.\n        // A rule with an invalid/empty pattern is left out here so it's skipped entirely.\n        var compiledRegex = new Dictionary<Rule, Regex>();\n        foreach (var rule in rules)\n        {","sourceCodeStart":374,"sourceCodeEnd":410,"githubUrl":"https://github.com/SubtitleEdit/subtitleedit/blob/17a9f0748781032255db3526b7215d2fb891e3af/src/seconv/Core/MultipleReplaceLoader.cs#L374-L410","documentation":"Thrown by MultipleReplaceLoader.Apply when the multiple-replace rules file does not exist (File.Exists returns false). Apply loads and applies active rules from the file to a subtitle — without the file there is nothing to apply. The exception is a FileNotFoundException with the path as FileName. Note: LoadRules (the lower-level method) does its own File.Exists check via ReadAllText's exception path, but Apply checks first for a clean error.","triggerScenarios":"Calling Apply(subtitle, path) where path does not resolve to an existing file. The path may be a typo, a relative path from the wrong CWD, or reference a file that was moved/deleted.","commonSituations":"CLI --multiple-replace with a mistyped path; a config referencing a rules file that was moved; a batch script using a relative path that breaks when CWD changes.","solutions":["Verify the path with File.Exists before calling Apply.","Resolve relative paths to absolute with Path.GetFullPath against the intended base directory.","Check for typos, trailing spaces, or shell-quoting issues in the path argument."],"exampleFix":"// before\nMultipleReplaceLoader.Apply(subtitle, rulesPath);\n\n// after\nif (!File.Exists(rulesPath))\n    throw new FileNotFoundException($\"Multiple-replace file not found: {rulesPath}\");\nMultipleReplaceLoader.Apply(subtitle, rulesPath);","handlingStrategy":"validation","validationCode":"if (!File.Exists(path))\n    throw new FileNotFoundException($\"Multiple-replace file not found: {path}\", path);\nMultipleReplaceLoader.Apply(subtitle, path);","typeGuard":"static bool IsReplaceFileReadable(string path) => File.Exists(path);","tryCatchPattern":"try { MultipleReplaceLoader.Apply(subtitle, path); }\ncatch (FileNotFoundException ex) when (ex.Message.Contains(\"Multiple-replace file not found\"))\n{ /* report missing rules file, check path/spelling */ }","preventionTips":["Validate File.Exists for the rules file path before calling Apply.","Resolve relative paths to absolute with Path.GetFullPath.","Store rules files in a known, version-controlled location and reference by absolute path."],"tags":["multiple-replace","file-not-found","validation","path","subtitles"],"backgroundTag":null,"analyzedSha":"17a9f0748781032255db3526b7215d2fb891e3af","analyzedAt":"2026-08-13T18:11:43.374Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}