TLDR: Missing Null check throwing uncaught error. Workaround provided. PR coming.
I discovered that when running cross_validation from prophet.diagnostics if you pass in a time series with a single constant value, or if there is both a sufficiently large enough sequence within the time series that is a constant value and a sufficiently small enough cross validation window to fit inside that sequence, then the following error will be thrown:
Traceback (most recent call last):
File "test/test.py", line 16, in <module>
cross_val = cross_validation(model, horizon='30 days')
File "test/.venv/lib/python3.13/site-packages/prophet/diagnostics.py", line 207, in cross_validation
single_cutoff_forecast(df, model, cutoff, horizon, predict_columns)
~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "test/.venv/lib/python3.13/site-packages/prophet/diagnostics.py", line 263, in single_cutoff_forecast
m.stan_backend.cleanup()
~~~~~~~~~~~~~~~~~~~~~~^^
File "test/.venv/lib/python3.13/site-packages/prophet/models.py", line 180, in cleanup
fit_result.runset.csv_files +
^^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'runset'
If you want to recreate this error, this simple script will throw it (example of successful values and erroring values):
import pandas as pd
from prophet import Prophet
from prophet.diagnostics import cross_validation
dates = pd.date_range(start='2025-01-01', end='2025-12-31')
# values = [1 + i for i in range(len(dates))] # good values, will succeed
values = [i // 100 for i in range(len(dates))] # bad values, will error
model = Prophet().fit(pd.DataFrame({'ds': dates, 'y': values}))
cross_val = cross_validation(model, horizon='30 days')
This error is ultimately getting thrown in CmdStanPyBackend.cleanup() a function that was included in the most recent release (1.1.7) with #2671.
That function does a check to see if the stan_fit class attribute exists, but currently does not check if the attribute is non-null. That attribute will be None though whenever any time series (or cross validation windows within a time series) satisfies this condition: self.history['y'].min() == self.history['y'].max() and (self.growth == 'linear' or self.growth == 'flat') which will cause that neither the fit() nor the sampling() method be called on the CmdStanPyBackend instance resulting that stan_fit remain in its default state of None all the way through the cleanup step, causing this error.
As a work around to correct for this bug until a release can be made, this code block can overwrite the existing function from the user code and add the null safe check:
from prophet.models import CmdStanPyBackend
_original_cleanup = CmdStanPyBackend.cleanup
CmdStanPyBackend.cleanup = lambda self: _original_cleanup(self) if self.stan_fit is not None else None
But ultimately a patch should be merged to replace this line with:
if hasattr(self, "stan_fit") and self.stan_fit is not None:
I'll put up a PR for it.
TLDR: Missing Null check throwing uncaught error. Workaround provided. PR coming.
I discovered that when running
cross_validationfromprophet.diagnosticsif you pass in a time series with a single constant value, or if there is both a sufficiently large enough sequence within the time series that is a constant value and a sufficiently small enough cross validation window to fit inside that sequence, then the following error will be thrown:If you want to recreate this error, this simple script will throw it (example of successful values and erroring values):
This error is ultimately getting thrown in CmdStanPyBackend.cleanup() a function that was included in the most recent release (1.1.7) with #2671.
That function does a check to see if the
stan_fitclass attribute exists, but currently does not check if the attribute is non-null. That attribute will beNonethough whenever any time series (or cross validation windows within a time series) satisfies this condition:self.history['y'].min() == self.history['y'].max() and (self.growth == 'linear' or self.growth == 'flat')which will cause that neither the fit() nor the sampling() method be called on theCmdStanPyBackendinstance resulting thatstan_fitremain in its default state ofNoneall the way through the cleanup step, causing this error.As a work around to correct for this bug until a release can be made, this code block can overwrite the existing function from the user code and add the null safe check:
But ultimately a patch should be merged to replace this line with:
I'll put up a PR for it.