google-research/timesfm · error · ValueError

Unsupported mode: {xreg_mode}

Error message

Unsupported mode: {xreg_mode}

What it means

`xreg_mode` must be exactly 'timesfm + xreg' or 'xreg + timesfm'; any other string (the f-string interpolates the offending value) is rejected with ValueError. The mode controls whether the residual model is fit on the pre-patch context ('timesfm + xreg') or the full input ('xreg + timesfm'), and unknown modes have no defined behavior. This is a strict enum-style validation of a string argument.

Source

Thrown at src/timesfm/timesfm_2p5/timesfm_2p5_base.py:274

        " dynamic_categorical_covariates, static_numerical_covariates,"
        " static_categorical_covariates must be set."
      )

    # Track the lengths of (1) each input, (2) the part that can be used in the
    # linear model, and (3) the horizon.
    input_lens, train_lens, test_lens = [], [], []

    for i, input_ts in enumerate(inputs):
      input_len = len(input_ts)
      input_lens.append(input_len)

      if xreg_mode == "timesfm + xreg":
        # For fitting residuals, no TimesFM forecast on the first patch.
        train_lens.append(max(0, input_len - self.model.p))
      elif xreg_mode == "xreg + timesfm":
        train_lens.append(input_len)
      else:
        raise ValueError(f"Unsupported mode: {xreg_mode}")

      if dynamic_numerical_covariates:
        test_lens.append(
          len(list(dynamic_numerical_covariates.values())[0][i]) - input_len
        )
      elif dynamic_categorical_covariates:
        test_lens.append(
          len(list(dynamic_categorical_covariates.values())[0][i]) - input_len
        )
      else:
        test_lens.append(self.forecast_config.max_horizon)

      if test_lens[-1] > self.forecast_config.max_horizon:
        raise ValueError(
          "Forecast horizon length inferred from the dynamic covariates is longer than the"
          f"max_horizon defined in the forecast config: {test_lens[-1]} > {self.forecast_config.max_horizon=}."
        )

View on GitHub (pinned to 331c6d33cb)

Solutions

  1. Use exactly 'timesfm + xreg' or 'xreg + timesfm' (lowercase, with spaces around '+')
  2. Validate the mode string against an allowlist before calling
  3. If you don't need residual covariate modeling, use plain forecast() instead

Example fix

// before
model.forecast_with_covariates(..., xreg_mode='timesfm+xreg', ...)
// after
model.forecast_with_covariates(..., xreg_mode='timesfm + xreg', ...)
Defensive patterns

Strategy: validation

Validate before calling

ALLOWED_XREG_MODES = {'timesfm + xreg', 'xreg + timesfm'}
if xreg_mode not in ALLOWED_XREG_MODES:
    raise ValueError(f'xreg_mode must be one of {ALLOWED_XREG_MODES}, got {xreg_mode!r}')

Type guard

from typing import Literal
XregMode = Literal['timesfm + xreg', 'xreg + timesfm']
def is_valid_xreg_mode(mode: str) -> bool:
    return mode in ('timesfm + xreg', 'xreg + timesfm')

Prevention

When it happens

Trigger: Passing xreg_mode values like 'xreg', 'timesfm+xreg' (missing spaces), 'TimesFM + XReg' (wrong case), or None; an application config file supplying a custom mode name; upgrading from TimesFM 1.x where covariate API had different parameter semantics.

Common situations: Typo or inconsistent spacing/casing in the mode string; reading the mode from CLI/config without validating against allowed values; mixing examples from different TimesFM versions.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


AI-assisted analysis of google-research/timesfm@331c6d33cb (2026-08-29). Data as JSON: /api/errors/e57f9902fe57f772. Report an issue: GitHub.