{"record":{"id":"75f615258f4be084","repo":"iOfficeAI/OfficeCLI","slug":"field-fieldname-not-found-in-source-headers","errorCode":null,"errorMessage":"field '{fieldName}' 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":361,"sourceCode":"                // the value-field, producing an empty pivot with no error.\n                // Reject up front with the available-index range so users\n                // catch the typo immediately (mirrors the throw used for\n                // unknown field names).\n                if (idx < 0 || idx >= headers.Length)\n                    throw new ArgumentException(\n                        $\"field index {idx} out of range (0..{headers.Length - 1})\");\n                fieldIdx = idx;\n            }\n            else\n            {\n                for (int i = 0; i < headers.Length; i++)\n                    if (FieldNameMatches(headers[i], fieldName)) { fieldIdx = i; break; }\n                // CONSISTENCY(field-name-validation): non-numeric token must\n                // resolve. Same throw shape as ParseFieldList.\n                if (fieldIdx < 0)\n                {\n                    var available = string.Join(\", \", headers.Where(h => !string.IsNullOrEmpty(h)));\n                    throw new ArgumentException($\"field '{fieldName}' not found in source headers: {available}\");\n                }\n            }\n\n            if (fieldIdx >= 0 && fieldIdx < headers.Length)\n            {\n                // R34-3: a user-supplied 4th (or 3rd-when-no-showAs) segment\n                // becomes the DataField.Name (the column header rendered in\n                // the pivot output). Falls back to \"{Func} of {Header}\" when\n                // absent — matches Excel's default and preserves the\n                // round-trip shape the existing prefix-strip relies on.\n                var displayName = !string.IsNullOrEmpty(customName)\n                    ? customName!\n                    : $\"{char.ToUpper(func[0])}{func[1..]} of {headers[fieldIdx]}\";\n                result.Add((fieldIdx, func, showAs, displayName));\n            }\n        }\n        return result;\n    }","sourceCodeStart":343,"sourceCodeEnd":379,"githubUrl":"https://github.com/iOfficeAI/OfficeCLI/blob/1ced45e900782c5083ed550ddf328ee974e425e7/src/officecli/Core/PivotTableHelper.Parse.cs#L343-L379","documentation":"The values= counterpart of error 327: a non-numeric field-name token in a value spec could not be matched to any source header. The matching uses the same case-insensitive, trimmed, NFC-normalised FieldNameMatches helper as the rows/cols/filters resolver, so the throw is identical in shape and the message lists the available headers.","triggerScenarios":"values=Revnue:sum when the header is 'Revenue'; values=Sale:sum:percent_of_total where 'Sale' is a typo; referencing a calculated-field name before it has been added (calc field names are not source headers).","commonSituations":"Typos; referencing calc fields by name in values= instead of letting them auto-attach; source columns renamed between sessions; locale-specific spellings.","solutions":["Match the header spelling exactly (see the 'available' list in the message)","If you meant a calculated field, ensure it is added in the same call so it resolves through the calc-field path","Use the column index if the name is unstable"],"exampleFix":"// before\nvalues=\"Revnue:sum\"\n// after\nvalues=\"Revenue:sum\"","handlingStrategy":"validation","validationCode":"var missing = valueFieldNames.Where(n => !headers.Any(h => FieldNameMatches(h, n))).ToList();\nif (missing.Count > 0) throw new InvalidOperationException($\"Unknown value fields: {string.Join(\", \", missing)}\");","typeGuard":"static bool ValueFieldExists(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{ /* re-prompt with the available list */ }","preventionTips":["Validate value-field names against the source header row","Do not reference calculated fields in values= before they are added","Use the available-list in the error to correct typos"],"tags":["pivottable","field-resolution","argument-validation","values-axis"],"backgroundTag":null,"analyzedSha":"1ced45e900782c5083ed550ddf328ee974e425e7","analyzedAt":"2026-08-13T13:01:07.193Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}