{"record":{"id":"ed69b97303e96c93","repo":"iOfficeAI/OfficeCLI","slug":"unknown-timeperiod-period-valid-today-yeste","errorCode":null,"errorMessage":"Unknown timePeriod '{period}'. Valid: today, yesterday, tomorrow, last7Days, thisWeek, lastWeek, nextWeek, thisMonth, lastMonth, nextMonth.","messagePattern":"Unknown timePeriod '(.+?)'\\. Valid: today, yesterday, tomorrow, last7Days, thisWeek, lastWeek, nextWeek, thisMonth, lastMonth, nextMonth\\.","errorType":"validation","errorClass":"System.ArgumentException","httpStatus":null,"severity":"error","filePath":"src/officecli/Handlers/Excel/ExcelHandler.Add.Cf.cs","lineNumber":785,"sourceCode":"                cfNewRule = new ConditionalFormattingRule\n                {\n                    Type = ConditionalFormatValues.TimePeriod,\n                    Priority = cfNewPriority,\n                    TimePeriod = new EnumValue<TimePeriodValues>(normalizedPeriod switch\n                    {\n                        \"today\" => TimePeriodValues.Today,\n                        \"yesterday\" => TimePeriodValues.Yesterday,\n                        \"tomorrow\" => TimePeriodValues.Tomorrow,\n                        \"last7Days\" => TimePeriodValues.Last7Days,\n                        \"thisWeek\" => TimePeriodValues.ThisWeek,\n                        \"lastWeek\" => TimePeriodValues.LastWeek,\n                        \"nextWeek\" => TimePeriodValues.NextWeek,\n                        \"thisMonth\" => TimePeriodValues.ThisMonth,\n                        \"lastMonth\" => TimePeriodValues.LastMonth,\n                        \"nextMonth\" => TimePeriodValues.NextMonth,\n                        // Silent-accept enum-miss family: an unknown period\n                        // must not quietly become \"today\".\n                        _ => throw new ArgumentException(\n                            $\"Unknown timePeriod '{period}'. Valid: today, yesterday, tomorrow, last7Days, thisWeek, lastWeek, nextWeek, thisMonth, lastMonth, nextMonth.\")\n                    })\n                };\n                break;\n            }\n            case \"belowaverage\":\n            {\n                cfNewRule = new ConditionalFormattingRule\n                {\n                    Type = ConditionalFormatValues.AboveAverage,\n                    Priority = cfNewPriority,\n                    AboveAverage = false\n                };\n                break;\n            }\n            case \"containsblanks\":\n            {\n                cfNewRule = new ConditionalFormattingRule","sourceCodeStart":767,"sourceCodeEnd":803,"githubUrl":"https://github.com/iOfficeAI/OfficeCLI/blob/1ced45e900782c5083ed550ddf328ee974e425e7/src/officecli/Handlers/Excel/ExcelHandler.Add.Cf.cs#L767-L803","documentation":"Thrown by the dateOccurring (timePeriod) case in AddCfExtended when the period value is not in the supported set. The period is read from 'period', 'timePeriod', or 'timeperiod' (default 'today'), normalized to lowercase, then mapped to the OOXML TimePeriodValues enum. Note the valid set uses camelCase tokens (last7Days, thisWeek, etc.) — the normalization lowercases input, so 'last7days' is accepted, but a genuinely unknown word is rejected rather than silently defaulted to 'today' (per the silent-accept enum-miss guard).","triggerScenarios":"Calling Add with type=dateOccurring/timePeriod (or cf type=dateoccurring) and a period/timePeriod/timeperiod property not matching (case-insensitively) today, yesterday, tomorrow, last7Days, thisWeek, lastWeek, nextWeek, thisMonth, lastMonth, nextMonth. Example: period=lastMonth1, period=thisQuarter.","commonSituations":"Asking for a period Excel does not offer as a built-in time-period rule (quarters, years, last14Days); typo; using the Excel UI label with extra characters.","solutions":["Use one of the supported period tokens: today, yesterday, tomorrow, last7Days, thisWeek, lastWeek, nextWeek, thisMonth, lastMonth, nextMonth (case-insensitive).","For unsupported periods (e.g. thisQuarter), build a formula-based CF rule with the equivalent date logic instead.","Omit period to accept the default 'today'."],"exampleFix":"// before: period=thisQuarter (not a built-in time period)\nadd /Sheet1/A1:A10 cf type=dateoccurring period=thisQuarter\n// after: use a supported period, or a formula rule\nadd /Sheet1/A1:A10 cf type=dateoccurring period=thisMonth","handlingStrategy":"validation","validationCode":"var periods = new HashSet<string>(StringComparer.OrdinalIgnoreCase)\n{ \"today\",\"yesterday\",\"tomorrow\",\"last7Days\",\"thisWeek\",\"lastWeek\",\"nextWeek\",\"thisMonth\",\"lastMonth\",\"nextMonth\" };\nvar p = properties.GetValueOrDefault(\"period\") ?? properties.GetValueOrDefault(\"timePeriod\") ?? properties.GetValueOrDefault(\"timeperiod\") ?? \"today\";\nif (!periods.Contains(p)) throw new ArgumentException($\"timePeriod '{p}' invalid.\");","typeGuard":"static readonly HashSet<string> TimePeriods = new(StringComparer.OrdinalIgnoreCase)\n{ \"today\",\"yesterday\",\"tomorrow\",\"last7Days\",\"thisWeek\",\"lastWeek\",\"nextWeek\",\"thisMonth\",\"lastMonth\",\"nextMonth\" };\nstatic bool IsValidTimePeriod(string? s) => s is null || TimePeriods.Contains(s);","tryCatchPattern":"try { return Add(path, \"cfextended\", pos, props); }\ncatch (ArgumentException ex) when (ex.Message.Contains(\"timePeriod\"))\n{ props[\"period\"] = \"today\"; return Add(path, \"cfextended\", pos, props); }","preventionTips":["Whitelist the period against the ten built-in Excel time periods.","For unsupported periods (quarters, years), use a formula-based CF rule.","Matching is case-insensitive, but spelling must match a real token."],"tags":["excel","conditional-formatting","date-occurring","time-period","enum-validation","argument-validation"],"backgroundTag":null,"analyzedSha":"1ced45e900782c5083ed550ddf328ee974e425e7","analyzedAt":"2026-08-13T13:01:07.193Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}