Skip to content

[BUG] Seasonal forecasting broken on user-loaded monthly data (MS DatetimeIndex vs PeriodIndex) #531

Description

@Shashankss1205

Severity: P0 — this is the single biggest UX blocker in the server today. Verified live over the MCP wire on 2026-08-09 (server at main cbac09f, sktime 1.0.1).

Problem

Any user who loads their own monthly data and picks a seasonal forecaster (sp > 1) hits a dead end: fit succeeds, then predict fails.

load_data_source(monthly sales, 30 rows)     -> DatetimeIndex, freq "MS"   OK
fit(NaiveForecaster(strategy="last", sp=12), y_handle=<handle>)            OK  {"fitted": true}
predict(estimator_handle, horizon=6)
  -> {"success": false, "error": "<MonthBegin> is not supported as period frequency"}

Same failure with AutoETS(auto=True, sp=12). The failure matrix (all confirmed live):

Demo dataset (PeriodIndex) Loaded handle (DatetimeIndex "MS")
Non-seasonal (sp=1) works works (incl. intervals)
Seasonal (sp>1) works fit OK, predict fails

Root cause

load_data_source normalizes monthly data to a DatetimeIndex with freq="MS" (MonthBegin), while sktime's demo datasets carry a PeriodIndex. Seasonal forecasters that internally call _pivot_sp do index.to_period(freq=MonthBegin), and pandas raises <MonthBegin> is not supported as period frequency. So fit (which doesn't pivot) succeeds and predict (which does) fails — a trap, because the user has no signal at fit time.

There is no workaround inside the toolset for datetime-indexed data; the only escapes are demo datasets, sp=1 models, or integer-index loading.

Related (same root cause)

  • NB-19update after a demo-dataset fit, with a load_data_source handle, fails the same way (demo PeriodIndex vs handle DatetimeIndex → object base Index deep in sktime).
  • This is also the trigger class behind the former evaluate all-NaN masking bug (fixed in commit fa26f5f / fix: surface per-fold exceptions in evaluate instead of NaN metrics #524, which now surfaces it honestly — but the underlying interop is still broken).

Proposed fix

Normalize period-compatible DatetimeIndex handles to PeriodIndex at load time (in load_data_source / format_data_handle), so handle-loaded data behaves like demo data. One change resolves this issue, NB-19, and the BUG-05 trigger class. Alternatively, pre-validate at fit time and fail with a clear message instead of letting fit succeed.

Re-verify

load_data_source 24+ monthly rows → fit(NaiveForecaster(sp=12))predict(horizon=6) must return a forecast.

(Catalogued as NB-20 / NB-19 in MCP_TEST_FINDINGS.md.)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions