{"record":{"id":"3cff227466285260","repo":"iOfficeAI/OfficeCLI","slug":"invalid-subtotals-s-valid-on-off-default-o","errorCode":null,"errorMessage":"Invalid subtotals '{s}'. Valid: on, off (default on)","messagePattern":"Invalid subtotals '(.+?)'\\. Valid: on, off \\(default on\\)","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/officecli/Core/PivotTableHelper.cs","lineNumber":544,"sourceCode":"    /// </summary>\n    private static IDisposable PushSubtotalsOptions(Dictionary<string, string> properties)\n    {\n        var prev = _defaultSubtotal;\n\n        if (properties.TryGetValue(\"subtotals\", out var s)\n            || properties.TryGetValue(\"Subtotals\", out s))\n        {\n            switch ((s ?? \"\").Trim().ToLowerInvariant())\n            {\n                case \"on\": case \"true\": case \"1\": case \"yes\": case \"show\":\n                    _defaultSubtotal = true; break;\n                case \"off\": case \"false\": case \"0\": case \"no\": case \"hide\": case \"none\":\n                    _defaultSubtotal = false; break;\n                // R35-2: previously unknown values silently fell through to the\n                // default (\"on\"). Reject explicitly so typos like\n                // \"subtotals=auto\" surface as errors instead of being misread.\n                default:\n                    throw new ArgumentException(\n                        $\"Invalid subtotals '{s}'. Valid: on, off (default on)\");\n            }\n        }\n\n        if (TryParseBoolProp(properties, \"defaultSubtotal\", out var ds))\n            _defaultSubtotal = ds;\n\n        return new SubtotalsScope(prev);\n    }\n\n    private sealed class SubtotalsScope : IDisposable\n    {\n        private readonly bool? _prev;\n        public SubtotalsScope(bool? prev) { _prev = prev; }\n        public void Dispose() { _defaultSubtotal = _prev; }\n    }\n\n    // ==================== Layout mode options ====================","sourceCodeStart":526,"sourceCodeEnd":562,"githubUrl":"https://github.com/iOfficeAI/OfficeCLI/blob/1ced45e900782c5083ed550ddf328ee974e425e7/src/officecli/Core/PivotTableHelper.cs#L526-L562","documentation":"Thrown by PushSubtotalsOptions when the 'subtotals' (or 'Subtotals') property value, after trimming and lowercasing, does not match any accepted token. Accepted on-values: on, true, 1, yes, show. Accepted off-values: off, false, 0, no, hide, none. Previously (pre-R35-2) unknown values silently fell through to the default 'on', masking typos; now they are rejected explicitly.","triggerScenarios":"Calling Add/Set pivot subtotals='auto' (not recognized); subtotals='enable'; subtotals='default'; or any value not in the accepted on/off token lists.","commonSituations":"Typo like subtotals='auto' instead of 'on'/'off'; using a synonym not in the accepted list (e.g. 'enable'/'disable'); assuming 'auto' is supported because Excel's UI uses that term.","solutions":["Use 'on' or 'off' (or their synonyms: true/false, 1/0, yes/no, show/hide, none for off).","If unsure, omit the subtotals property to accept the default (on).","Check the exact spelling — it is case-insensitive but must match a known token."],"exampleFix":"// before\nSet pivot subtotals='auto'\n// after\nSet pivot subtotals='on'","handlingStrategy":"validation","validationCode":"var validOn = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { \"on\", \"true\", \"1\", \"yes\", \"show\" };\nvar validOff = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { \"off\", \"false\", \"0\", \"no\", \"hide\", \"none\" };\nvar v = subtotalsValue.Trim().ToLowerInvariant();\nif (!validOn.Contains(v) && !validOff.Contains(v))\n    throw new ArgumentException($\"Invalid subtotals '{subtotalsValue}'. Valid: on, off.\");","typeGuard":"static readonly HashSet<string> SubtotalTokens =\n    new(StringComparer.OrdinalIgnoreCase)\n    { \"on\",\"true\",\"1\",\"yes\",\"show\",\"off\",\"false\",\"0\",\"no\",\"hide\",\"none\" };\nstatic bool IsValidSubtotals(string val) =>\n    string.IsNullOrWhiteSpace(val) || SubtotalTokens.Contains(val.Trim().ToLowerInvariant());","tryCatchPattern":null,"preventionTips":["Use 'on' or 'off' as the canonical tokens.","Omit the subtotals property entirely to accept the default (on).","Do not assume 'auto' is supported — it is not."],"tags":["pivot","excel","subtotals","enum","validation","input-validation"],"backgroundTag":null,"analyzedSha":"1ced45e900782c5083ed550ddf328ee974e425e7","analyzedAt":"2026-08-13T13:01:07.193Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}