google-research/timesfm · error · ValueError
Horizon must be less than the max horizon. {horizon} > {fc.m
Error message
Horizon must be less than the max horizon. {horizon} > {fc.max_horizon}. What it means
_compiled_decode is the compiled inference closure created inside compile(); torch.compile fixes graph shapes sized by forecast_config.max_horizon, so requesting a horizon larger than the compiled maximum raises ValueError at inference time. Every forecast() call on a compiled model passes through this check.
Source
Thrown at src/timesfm/timesfm_2p5/timesfm_2p5_torch.py:423
self.model.o,
new_horizon := math.ceil(fc.max_horizon / self.model.o) * self.model.o,
)
fc = dataclasses.replace(fc, max_horizon=new_horizon)
if fc.max_context + fc.max_horizon > self.model.config.context_limit:
raise ValueError(
"Context + horizon must be less than the context limit."
f" {fc.max_context} + {fc.max_horizon} >"
f" {self.model.config.context_limit}."
)
if fc.use_continuous_quantile_head and (fc.max_horizon > self.model.os):
raise ValueError(
f"Continuous quantile head is not supported for horizons > {self.model.os}."
)
self.forecast_config = fc
def _compiled_decode(horizon, inputs, masks):
if horizon > fc.max_horizon:
raise ValueError(
f"Horizon must be less than the max horizon. {horizon} > {fc.max_horizon}."
)
inputs = (
torch.from_numpy(np.array(inputs)).to(self.model.device).to(torch.float32)
)
masks = torch.from_numpy(np.array(masks)).to(self.model.device).to(torch.bool)
batch_size = inputs.shape[0]
if fc.infer_is_positive:
is_positive = torch.all(inputs >= 0, dim=-1, keepdim=True)
else:
is_positive = None
if fc.normalize_inputs:
mu = torch.mean(inputs, dim=-1, keepdim=True)
sigma = torch.std(inputs, dim=-1, keepdim=True)
inputs = revin(inputs, mu, sigma, reverse=False)View on GitHub (pinned to 331c6d33cb)
Solutions
- Recompile with a larger max_horizon (multiple of output patch length 128) covering every horizon you request.
- Clamp the per-call horizon to model.forecast_config.max_horizon before calling forecast.
- Compile once with the largest needed horizon and slice outputs down for smaller requests.
- Keep compile-time max_horizon and inference horizons in the same app config so they stay in sync.
Example fix
// before model.compile(ForecastConfig(max_horizon=128)) model.forecast(horizon=256, inputs=...) # ValueError: 256 > 128 // after model.compile(ForecastConfig(max_horizon=256)) model.forecast(horizon=256, inputs=...) # OK
Defensive patterns
Strategy: validation
Validate before calling
max_h = model.forecast_config.max_horizon horizon = min(horizon, max_h) predictions = model.forecast(horizon=horizon, inputs=inputs)
Try / catch
try:
preds = model.forecast(horizon=h, inputs=inputs)
except ValueError as e:
if "max horizon" in str(e):
h = model.forecast_config.max_horizon
preds = model.forecast(horizon=h, inputs=inputs)
else:
raise Prevention
- Compile with the largest horizon you will ever request.
- Clamp request horizons to model.forecast_config.max_horizon.
- Slice compiled outputs for smaller horizons instead of recompiling.
- Keep compile-time max_horizon and inference horizons in shared config.
When it happens
Trigger: Calling model.forecast(horizon=N) (or forecast_on_df) with N greater than the max_horizon supplied to the preceding compile() — e.g. compile with max_horizon=128 then forecast(horizon=256).
Common situations: Choosing the horizon per-request after compiling with a small max_horizon; reusing a compiled model configured for short horizons in a new long-horizon use case; confusion because max_horizon was silently rounded up to a multiple of 128 at compile time.
Related errors
- Context + horizon must be less than the context limit. {fc.m
- Continuous quantile head is not supported for horizons > {se
- Activation: {config.activation} not supported.
- Output dims must be a multiple of 4: {config.output_dims} %
- Memory dimension ({self.in_features}) must be divisible by '
AI-assisted analysis of google-research/timesfm@331c6d33cb (2026-08-29).
Data as JSON: /api/errors/e6fc9dedc8e0cc99.
Report an issue: GitHub.