{"record":{"id":"cda5aa69f731667f","repo":"iOfficeAI/OfficeCLI","slug":"field-name-not-found-in-source-headers-avail","errorCode":null,"errorMessage":"field '{name}' not found in source headers: {available}","messagePattern":"field '(.+?)' not found in source headers: (.+?)","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/officecli/Core/PivotTableHelper.Parse.cs","lineNumber":115,"sourceCode":"            // CONSISTENCY(date-grouping-passthrough): unrecognized grouping\n            // suffixes (e.g. \"Date:hours\") survive ApplyDateGrouping as\n            // literals. Strip the suffix and re-resolve so the bare field\n            // name still binds — matches the existing best-effort fuzz\n            // contract that says invalid grouping must not crash.\n            if (found < 0)\n            {\n                var colon = name.IndexOf(':');\n                if (colon > 0)\n                {\n                    var bare = name.Substring(0, colon);\n                    for (int i = 0; i < headers.Length; i++)\n                        if (FieldNameMatches(headers[i], bare)) { found = i; break; }\n                }\n            }\n            if (found < 0)\n            {\n                var available = string.Join(\", \", headers.Where(h => !string.IsNullOrEmpty(h)));\n                throw new ArgumentException($\"field '{name}' not found in source headers: {available}\");\n            }\n            if (seen.Add(found)) result.Add(found);\n        }\n        return result;\n    }\n\n    private static List<(int idx, string func, string showAs, string name)> ParseValueFields(\n        Dictionary<string, string> props, string key, string[] headers)\n    {\n        if (!props.TryGetValue(key, out var value) || string.IsNullOrEmpty(value))\n            return new List<(int, string, string, string)>();\n\n        // CONSISTENCY(aggregate-override): the optional sibling 'aggregate'\n        // property is a comma-list aligned positionally with 'values'. It\n        // overrides the per-field func parsed from the colon-suffix syntax.\n        // This lets users write `values=Sales,Sales aggregate=sum,count`\n        // instead of `values=Sales:sum,Sales:count` — both forms are\n        // equivalent. Per-spec colon syntax still wins for any slot the","sourceCodeStart":97,"sourceCodeEnd":133,"githubUrl":"https://github.com/iOfficeAI/OfficeCLI/blob/1ced45e900782c5083ed550ddf328ee974e425e7/src/officecli/Core/PivotTableHelper.Parse.cs#L97-L133","documentation":"Thrown by ParseFieldList when resolving row/col/filter field tokens: a non-numeric token could not be matched against any source header (after the date-grouping suffix-strip fallback also failed). The error message lists the available non-empty headers so the user can spot the typo. Matching is case-insensitive, trims surrounding whitespace, and normalises Unicode to NFC before comparing, so genuine spelling/normalisation differences are already accounted for.","triggerScenarios":"rows=Regin when the header is 'Region'; cols=PostlCode (typo); a field name with a CJK/Unicode variant that even NFC normalisation cannot reconcile; using a display label that differs from the underlying header.","commonSituations":"Typos in CLI input; renamed source columns the user has not noticed; mismatched locale/normalisation between data export and pivot input; reference to a column that lives in a different sheet than the source range.","solutions":["Read the 'available' list in the error and correct the spelling to match exactly","Re-check the source range header row (the first row of the pivot source) for the actual column name","If you want positional addressing, pass the column index instead of the name"],"exampleFix":"// before\nrows=\"Regin,Product\"\n// after\nrows=\"Region,Product\"","handlingStrategy":"validation","validationCode":"var available = headers.Where(h => !string.IsNullOrEmpty(h)).ToList();\nvar missing = requestedNames.Where(n => !available.Any(h => FieldNameMatches(h, n))).ToList();\nif (missing.Count > 0) throw new InvalidOperationException($\"Unknown fields: {string.Join(\", \", missing)}\");","typeGuard":"static bool FieldExists(string[] headers, string name) =>\n    headers.Any(h => h.Trim().Normalize(NormalizationForm.FormC)\n        .Equals(name.Trim().Normalize(NormalizationForm.FormC), StringComparison.OrdinalIgnoreCase));","tryCatchPattern":"try { BuildPivot(props); }\ncatch (ArgumentException ex) when (ex.Message.Contains(\"not found in source headers\"))\n{ /* read available list from message and re-prompt */ }","preventionTips":["Read the source header row first and validate field names against it","Prefer exact spelling from the source over guessed labels","Use positional indices only when the schema is stable"],"tags":["pivottable","field-resolution","argument-validation","input-parsing"],"backgroundTag":null,"analyzedSha":"1ced45e900782c5083ed550ddf328ee974e425e7","analyzedAt":"2026-08-13T13:01:07.193Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}