{"record":{"id":"19b058ab08e5189c","repo":"iOfficeAI/OfficeCLI","slug":"unknown-totals-row-function-tok-valid-sum-a","errorCode":null,"errorMessage":"Unknown totals-row function '{tok}'. Valid: sum, average, count, countNums, max, min, stdDev, var, none, custom.","messagePattern":"Unknown totals-row function '(.+?)'\\. Valid: sum, average, count, countNums, max, min, stdDev, var, none, custom\\.","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/officecli/Handlers/Excel/ExcelHandler.Helpers.Cell.cs","lineNumber":37,"sourceCode":"    // Map a table-column totals-row function token to its OOXML enum and the\n    // SUBTOTAL function code Excel uses. Unknown tokens throw — the earlier\n    // SUM fallback silently changed the aggregation the user asked for\n    // (silent-accept enum-miss family). Every token the dump emitter can\n    // produce (TotalsRowFunction InnerText, lowercased) is enumerated below,\n    // so dump→batch replay never hits the throw.\n    internal static (TotalsRowFunctionValues, int) MapTotalsRowFunction(string tok) => tok switch\n    {\n        \"sum\" => (TotalsRowFunctionValues.Sum, 109),\n        \"average\" or \"avg\" => (TotalsRowFunctionValues.Average, 101),\n        \"count\" => (TotalsRowFunctionValues.Count, 103),\n        \"countnums\" or \"countnumbers\" => (TotalsRowFunctionValues.CountNumbers, 102),\n        \"max\" or \"maximum\" => (TotalsRowFunctionValues.Maximum, 104),\n        \"min\" or \"minimum\" => (TotalsRowFunctionValues.Minimum, 105),\n        \"stddev\" or \"stdev\" => (TotalsRowFunctionValues.StandardDeviation, 107),\n        \"var\" or \"variance\" => (TotalsRowFunctionValues.Variance, 110),\n        \"none\" or \"label\" or \"\" => (TotalsRowFunctionValues.None, 0),\n        \"custom\" => (TotalsRowFunctionValues.Custom, 109),\n        _ => throw new ArgumentException(\n            $\"Unknown totals-row function '{tok}'. Valid: sum, average, count, countNums, max, min, stdDev, var, none, custom.\")\n    };\n\n    private string GetCellDisplayValue(Cell cell, Core.FormulaEvaluator? evaluator = null)\n    {\n        if (cell.DataType?.Value == CellValues.InlineString)\n        {\n            return cell.InlineString?.InnerText ?? \"\";\n        }\n\n        var value = cell.CellValue?.Text ?? \"\";\n\n        if (cell.DataType?.Value == CellValues.SharedString)\n        {\n            var sst = _doc.WorkbookPart?.GetPartsOfType<SharedStringTablePart>().FirstOrDefault();\n            if (sst?.SharedStringTable != null && int.TryParse(value, out int idx))\n            {\n                var item = sst.SharedStringTable.Elements<SharedStringItem>().ElementAtOrDefault(idx);","sourceCodeStart":19,"sourceCodeEnd":55,"githubUrl":"https://github.com/iOfficeAI/OfficeCLI/blob/1ced45e900782c5083ed550ddf328ee974e425e7/src/officecli/Handlers/Excel/ExcelHandler.Helpers.Cell.cs#L19-L55","documentation":"Thrown by MapTotalsRowFunction when a per-column totalsRowFunction token matches none of the switch arms. The caller (AddTable path, Add.Tables.cs:1565) splits properties[\"totalsRowFunction\"] on commas and lowercases each token before mapping. Note the message advertises 'countNums' but the switch is case-insensitive and also accepts aliases NOT in the message: 'avg', 'countnumbers', 'maximum', 'minimum', 'stdev', 'variance', 'label', and empty string. Unknown aggregations like 'median' or 'counta' are not supported by the OOXML totals-row enum.","triggerScenarios":"totalsRowFunction=\"sum,median,average\" (median unsupported); totalsRowFunction=\"counta\"; totalsRowFunction=\"subtotal\"; totalsRowFunction=\"total\".","commonSituations":"User typed an Excel UI label or a formula name instead of the enum token; copied 'Count Numbers' literally; expected an aggregation the OOXML totals row does not offer.","solutions":["Use a supported token (sum, average/avg, count, countNums/countnumbers, max/maximum, min/minimum, stdDev/stdev, var/variance, none/label, custom).","Leave the token empty for non-first columns to get the default (Sum); for column 0 empty means label.","For unsupported aggregations, set totalsRowFunction=custom and write the SUBTOTAL formula into the totals cell directly.","Validate each token against the allowed set before calling AddTable."],"exampleFix":"// before\nprops[\"totalsRowFunction\"] = \"label,sum,median\"; // 'median' -> throw\n\n// after\nprops[\"totalsRowFunction\"] = \"label,sum,average\";\n// or, for a custom aggregation on col 2:\nprops[\"totalsRowFunction\"] = \"none,sum,custom\";","handlingStrategy":"validation","validationCode":"static readonly HashSet<string> ValidTotals = new(StringComparer.OrdinalIgnoreCase)\n{ \"sum\",\"average\",\"avg\",\"count\",\"countnums\",\"countnumbers\",\"max\",\"maximum\",\n  \"min\",\"minimum\",\"stddev\",\"stdev\",\"var\",\"variance\",\"none\",\"label\",\"\",\"custom\" };\nvar bad = tokens.Where(t => !ValidTotals.Contains(t)).ToList();\nif (bad.Any()) throw new ArgumentException($\"Unsupported totals tokens: {string.Join(\",\",bad)}\");","typeGuard":"static bool IsValidTotalsToken(string t) =>\n    (new[] { \"sum\",\"average\",\"avg\",\"count\",\"countnums\",\"countnumbers\",\n      \"max\",\"maximum\",\"min\",\"minimum\",\"stddev\",\"stdev\",\"var\",\"variance\",\n      \"none\",\"label\",\"\",\"custom\" }).Contains(t, StringComparer.OrdinalIgnoreCase);","tryCatchPattern":null,"preventionTips":["Validate each comma-separated token against the allowed set before AddTable.","Remember the switch accepts aliases (avg, maximum, stdev, variance, label) not in the error message.","Use 'custom' plus a written SUBTOTAL formula for aggregations the enum lacks.","Leave non-first column tokens empty for the Sum default."],"tags":["excel","ooxml","table","totals-row","validation"],"backgroundTag":null,"analyzedSha":"1ced45e900782c5083ed550ddf328ee974e425e7","analyzedAt":"2026-08-13T13:01:07.193Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}