{"record":{"id":"85935be75945396e","repo":"iOfficeAI/OfficeCLI","slug":"invalid-path-path-empty-path-segment-i","errorCode":null,"errorMessage":"Invalid path '{path}': empty path segment ('//') is not allowed.","messagePattern":"Invalid path '(.+?)': empty path segment \\('//'\\) is not allowed\\.","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"warning","filePath":"src/officecli/Handlers/Excel/ExcelHandler.Helpers.Sheet.cs","lineNumber":111,"sourceCode":"    // quotes and un-double embedded quotes ('It''s'!A1 → It's). Excel REQUIRES\n    // the quoted form for names with spaces/punctuation, so refs pasted from\n    // formulas arrive quoted. Unquoted names pass through unchanged.\n    internal static string UnquoteSheetName(string s)\n        => s.Length >= 2 && s[0] == '\\'' && s[^1] == '\\''\n            ? s[1..^1].Replace(\"''\", \"'\")\n            : s;\n\n    internal string NormalizeExcelPath(string path)\n    {\n        // Reject malformed segment separators that previously slipped past\n        // the regex matchers and exposed raw OOXML local names. DOCX already\n        // rejects these; bring XLSX up to parity.\n        if (path.Length > 1 && path != \"/\" && path.EndsWith(\"/\"))\n            throw new ArgumentException($\"Invalid path '{path}': trailing '/' is not allowed.\");\n        if (path.StartsWith(\"//\"))\n            throw new ArgumentException($\"Invalid path '{path}': leading '//' is not allowed.\");\n        if (path.Contains(\"//\"))\n            throw new ArgumentException($\"Invalid path '{path}': empty path segment ('//') is not allowed.\");\n        // Handle \"/Sheet1!A1\" — strip leading '/' when '!' is present so native\n        // notation is parsed correctly. EXCEPT when the first slash segment\n        // names an existing sheet: '!' is legal inside a sheet NAME (Excel\n        // forbids only : \\ / ? * [ ]), and reinterpreting \"/Q1!Results\" as\n        // bang notation made such a sheet permanently unaddressable.\n        if (path.StartsWith('/') && path.Contains('!'))\n        {\n            var seg0 = path[1..];\n            var seg0Slash = seg0.IndexOf('/');\n            var first = seg0Slash < 0 ? seg0 : seg0[..seg0Slash];\n            if (!GetWorksheets().Any(w => w.Name.Equals(first, StringComparison.OrdinalIgnoreCase)))\n                path = path[1..];\n        }\n        if (path.Equals(\"/workbook\", StringComparison.OrdinalIgnoreCase)) return \"/\";\n        if (path.StartsWith('/')) return path;\n        // Excel-quoted sheet ref: 'My Data'!A1 — the '!' separator is the one\n        // FOLLOWING the closing quote (the name itself may contain '!').\n        string? qSheet = null; var rest = \"\";","sourceCodeStart":93,"sourceCodeEnd":129,"githubUrl":"https://github.com/iOfficeAI/OfficeCLI/blob/1ced45e900782c5083ed550ddf328ee974e425e7/src/officecli/Handlers/Excel/ExcelHandler.Helpers.Sheet.cs#L93-L129","documentation":"Thrown by NormalizeExcelPath when the path contains '//' anywhere (after the leading-slash check). This indicates an empty interior segment, which previously slipped past regex matchers and exposed raw OOXML local names. DOCX already rejected this; XLSX was brought to parity.","triggerScenarios":"Calling an Excel path API with '/Sheet1//A1', '/A/B//C', '/Sheet1///table[1]', or any path with two consecutive slashes not at the start (that case is error 705).","commonSituations":"Splitting and rejoining segments where an intermediate segment is empty; user input with accidental double-slash; transforming a path through a filter that drops an empty middle component.","solutions":["Filter out empty segments before joining: split on '/', remove empties, rejoin with single '/'.","Validate with a single Contains(\"//\") check and refuse early.","Use a small path-builder helper that never emits empty segments."],"exampleFix":"// before\nstring path = \"/\" + string.Join('/', segments); // segments may contain \"\"\n// after\nstring path = \"/\" + string.Join('/', segments.Where(s => !string.IsNullOrEmpty(s)));","handlingStrategy":"validation","validationCode":"static bool HasEmptySegment(string p) => p.Contains(\"//\");\nstatic string CollapseSlashes(string p)\n    => System.Text.RegularExpressions.Regex.Replace(p, \"/{2,}\", \"/\");","typeGuard":"null","tryCatchPattern":"try { NormalizeExcelPath(path); }\ncatch (ArgumentException ex) when (ex.Message.Contains(\"empty path segment\"))\n{ path = System.Text.RegularExpressions.Regex.Replace(path, \"/{2,}\", \"/\"); }","preventionTips":["Filter empty segments when building paths programmatically.","Treat '//' anywhere as a defect, not a normalizer input.","Sanitize user-supplied paths at the boundary."],"tags":["paths","excel","input-validation","normalization"],"backgroundTag":null,"analyzedSha":"1ced45e900782c5083ed550ddf328ee974e425e7","analyzedAt":"2026-08-13T13:01:07.193Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}