{"record":{"id":"debc3e66cb3f386d","repo":"iOfficeAI/OfficeCLI","slug":"invalid-sheet-name-name-contains-forbidden-ch","errorCode":null,"errorMessage":"Invalid sheet name '{name}': contains forbidden character '{name[hit]}'. Excel rejects any of: \\ / ? * : [ ]","messagePattern":"Invalid sheet name '(.+?)': contains forbidden character '(.+?)'\\. Excel rejects any of: \\\\ / \\? \\* : \\[ \\]","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/officecli/Handlers/Excel/ExcelHandler.Helpers.Validation.cs","lineNumber":329,"sourceCode":"            {\n                throw new ArgumentException(\n                    $\"Formula contains out-of-range cell reference '{m.Value}'. \" +\n                    \"Excel limits: rows 1-1048576, columns A-XFD.\");\n            }\n        }\n    }\n\n    internal static void ValidateSheetName(string name)\n    {\n        if (string.IsNullOrWhiteSpace(name))\n            throw new ArgumentException(\"Invalid sheet name: name cannot be empty or whitespace.\");\n        if (name.Length > 31)\n            throw new ArgumentException(\n                $\"Invalid sheet name '{name}': length {name.Length} exceeds Excel's 31-char limit.\");\n        var forbidden = new[] { '\\\\', '/', '?', '*', ':', '[', ']' };\n        var hit = name.IndexOfAny(forbidden);\n        if (hit >= 0)\n            throw new ArgumentException(\n                $\"Invalid sheet name '{name}': contains forbidden character '{name[hit]}'. Excel rejects any of: \\\\ / ? * : [ ]\");\n        if (name.StartsWith('\\'') || name.EndsWith('\\''))\n            throw new ArgumentException(\n                $\"Invalid sheet name '{name}': cannot start or end with an apostrophe (').\");\n        if (name.Equals(\"History\", StringComparison.OrdinalIgnoreCase))\n            throw new ArgumentException(\n                \"Invalid sheet name 'History': reserved by Excel for the change-history sheet.\");\n    }\n\n    /// <summary>\n    /// R35-3: cross-workbook cell formulas like \"=[Other.xlsx]Sheet1!A1\" or\n    /// \"=[1]Sheet1!A1\" need an externalLinks part to resolve. Without one,\n    /// Excel opens the file but the formula shows #REF!. Reject up-front\n    /// rather than silently persist a broken formula.\n    /// CONSISTENCY(cross-workbook-ref): mirrors the namedrange refersTo\n    /// guard in ExcelHandler.Add.Tables.cs (R27-1).\n    /// </summary>\n    internal static void RejectCrossWorkbookFormula(string formula)","sourceCodeStart":311,"sourceCodeEnd":347,"githubUrl":"https://github.com/iOfficeAI/OfficeCLI/blob/1ced45e900782c5083ed550ddf328ee974e425e7/src/officecli/Handlers/Excel/ExcelHandler.Helpers.Validation.cs#L311-L347","documentation":"Excel forbids the characters \\ / ? * : [ ] in worksheet names because they collide with path separators, wildcard operators, and sheet-name quoting in formulas. The library scans with IndexOfAny over the forbidden array and reports the first hit, so the file stays openable.","triggerScenarios":"Any sheet name containing one of \\ / ? * : [ ]. Common culprits: dates formatted with '/' or ':', file paths used as names, wildcard patterns, bracketed indices.","commonSituations":"Deriving a sheet name from a filename (e.g. '2026/03/data.csv'); embedding a date '2026:03:01'; using a regex or glob pattern as a label; copying a name from a URL.","solutions":["Strip or replace the forbidden characters (e.g. replace '/' with '-' or '_').","Run a sanitize helper over user input before passing to AddSheet.","Avoid reusing file paths or date strings verbatim as sheet names."],"exampleFix":"// before\nwb.AddSheet(\"2026/03/report\");   // contains '/'\n\n// after\nstatic string SanitizeSheetName(string s) {\n    var set = new HashSet<char>(\"\\\\/?*:[\");\n    set.Add(']');\n    return new string(s.Select(c => set.Contains(c) ? '_' : c).ToArray());\n}\nwb.AddSheet(SanitizeSheetName(\"2026/03/report\"));   // \"2026_03_report\"","handlingStrategy":"validation","validationCode":"static readonly char[] SheetForbidden = { '\\\\', '/', '?', '*', ':', '[', ']' };\nstatic string SanitizeSheetName(string n) {\n    var hit = n.IndexOfAny(SheetForbidden);\n    return hit < 0 ? n : new string(n.Select(c => SheetForbidden.Contains(c) ? '_' : c).ToArray());\n}","typeGuard":null,"tryCatchPattern":"try { wb.AddSheet(name); }\ncatch (ArgumentException ex) when (ex.Message.Contains(\"forbidden character\")) {\n    wb.AddSheet(SanitizeSheetName(name));\n}","preventionTips":["Always sanitize names derived from filenames, paths, or dates.","Centralize sheet-name sanitization in one helper used by every call site."],"tags":["excel","sheet-name","validation","characters"],"backgroundTag":null,"analyzedSha":"1ced45e900782c5083ed550ddf328ee974e425e7","analyzedAt":"2026-08-13T13:01:07.193Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}