iOfficeAI/OfficeCLI · error · System.ArgumentException

Unknown timePeriod '{period}'. Valid: today, yesterday, tomo

Error message

Unknown timePeriod '{period}'. Valid: today, yesterday, tomorrow, last7Days, thisWeek, lastWeek, nextWeek, thisMonth, lastMonth, nextMonth.

What it means

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).

Source

Thrown at src/officecli/Handlers/Excel/ExcelHandler.Add.Cf.cs:785

                cfNewRule = new ConditionalFormattingRule
                {
                    Type = ConditionalFormatValues.TimePeriod,
                    Priority = cfNewPriority,
                    TimePeriod = new EnumValue<TimePeriodValues>(normalizedPeriod switch
                    {
                        "today" => TimePeriodValues.Today,
                        "yesterday" => TimePeriodValues.Yesterday,
                        "tomorrow" => TimePeriodValues.Tomorrow,
                        "last7Days" => TimePeriodValues.Last7Days,
                        "thisWeek" => TimePeriodValues.ThisWeek,
                        "lastWeek" => TimePeriodValues.LastWeek,
                        "nextWeek" => TimePeriodValues.NextWeek,
                        "thisMonth" => TimePeriodValues.ThisMonth,
                        "lastMonth" => TimePeriodValues.LastMonth,
                        "nextMonth" => TimePeriodValues.NextMonth,
                        // Silent-accept enum-miss family: an unknown period
                        // must not quietly become "today".
                        _ => throw new ArgumentException(
                            $"Unknown timePeriod '{period}'. Valid: today, yesterday, tomorrow, last7Days, thisWeek, lastWeek, nextWeek, thisMonth, lastMonth, nextMonth.")
                    })
                };
                break;
            }
            case "belowaverage":
            {
                cfNewRule = new ConditionalFormattingRule
                {
                    Type = ConditionalFormatValues.AboveAverage,
                    Priority = cfNewPriority,
                    AboveAverage = false
                };
                break;
            }
            case "containsblanks":
            {
                cfNewRule = new ConditionalFormattingRule

View on GitHub (pinned to 1ced45e900)

Solutions

  1. Use one of the supported period tokens: today, yesterday, tomorrow, last7Days, thisWeek, lastWeek, nextWeek, thisMonth, lastMonth, nextMonth (case-insensitive).
  2. For unsupported periods (e.g. thisQuarter), build a formula-based CF rule with the equivalent date logic instead.
  3. Omit period to accept the default 'today'.

Example fix

// before: period=thisQuarter (not a built-in time period)
add /Sheet1/A1:A10 cf type=dateoccurring period=thisQuarter
// after: use a supported period, or a formula rule
add /Sheet1/A1:A10 cf type=dateoccurring period=thisMonth
Defensive patterns

Strategy: validation

Validate before calling

var periods = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
{ "today","yesterday","tomorrow","last7Days","thisWeek","lastWeek","nextWeek","thisMonth","lastMonth","nextMonth" };
var p = properties.GetValueOrDefault("period") ?? properties.GetValueOrDefault("timePeriod") ?? properties.GetValueOrDefault("timeperiod") ?? "today";
if (!periods.Contains(p)) throw new ArgumentException($"timePeriod '{p}' invalid.");

Type guard

static readonly HashSet<string> TimePeriods = new(StringComparer.OrdinalIgnoreCase)
{ "today","yesterday","tomorrow","last7Days","thisWeek","lastWeek","nextWeek","thisMonth","lastMonth","nextMonth" };
static bool IsValidTimePeriod(string? s) => s is null || TimePeriods.Contains(s);

Try / catch

try { return Add(path, "cfextended", pos, props); }
catch (ArgumentException ex) when (ex.Message.Contains("timePeriod"))
{ props["period"] = "today"; return Add(path, "cfextended", pos, props); }

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of iOfficeAI/OfficeCLI@1ced45e900 (2026-08-13). Data as JSON: /api/errors/ed69b97303e96c93. Report an issue: GitHub.