{"record":{"id":"c63d70ddf1b41a7b","repo":"google-research/timesfm","slug":"at-least-one-of-dynamic-numerical-covariates-dyna","errorCode":null,"errorMessage":"At least one of dynamic_numerical_covariates, dynamic_categorical_covariates, static_numerical_covariates, static_categorical_covariates must be set.","messagePattern":"At least one of dynamic_numerical_covariates, dynamic_categorical_covariates, static_numerical_covariates, static_categorical_covariates must be set\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/timesfm/timesfm_2p5/timesfm_2p5_base.py","lineNumber":254,"sourceCode":"      the outputs of the xreg.\n    \"\"\"\n    if self.forecast_config is None:\n      raise ValueError(\"Model is not compiled. Please call compile() first.\")\n    elif not self.forecast_config.return_backcast:\n      raise ValueError(\n        \"For XReg, `return_backcast` must be set to True in the forecast config. Please recompile the model.\"\n      )\n\n    from ..utils import xreg_lib\n\n    # Verify and bookkeep covariates.\n    if not (\n      dynamic_numerical_covariates\n      or dynamic_categorical_covariates\n      or static_numerical_covariates\n      or static_categorical_covariates\n    ):\n      raise ValueError(\n        \"At least one of dynamic_numerical_covariates,\"\n        \" dynamic_categorical_covariates, static_numerical_covariates,\"\n        \" static_categorical_covariates must be set.\"\n      )\n\n    # Track the lengths of (1) each input, (2) the part that can be used in the\n    # linear model, and (3) the horizon.\n    input_lens, train_lens, test_lens = [], [], []\n\n    for i, input_ts in enumerate(inputs):\n      input_len = len(input_ts)\n      input_lens.append(input_len)\n\n      if xreg_mode == \"timesfm + xreg\":\n        # For fitting residuals, no TimesFM forecast on the first patch.\n        train_lens.append(max(0, input_len - self.model.p))\n      elif xreg_mode == \"xreg + timesfm\":\n        train_lens.append(input_len)","sourceCodeStart":236,"sourceCodeEnd":272,"githubUrl":"https://github.com/google-research/timesfm/blob/331c6d33cb1ac2611de3056d0ac7164aab6301eb/src/timesfm/timesfm_2p5/timesfm_2p5_base.py#L236-L272","documentation":"`forecast_with_covariates()` exists solely to model covariates alongside the base forecast; calling it with all four covariate dicts (dynamic_numerical_covariates, dynamic_categorical_covariates, static_numerical_covariates, static_categorical_covariates) empty gives it nothing to do, so it raises ValueError. Use the plain `forecast()` method when you have no covariates.","triggerScenarios":"Calling `forecast_with_covariates` with default (None/empty) covariate arguments; covariates loaded conditionally (e.g. empty dict because a file/feature store returned nothing) and then passed in; programmatically building covariate dicts that end up empty.","commonSituations":"Feature pipeline returned no rows; typo in covariate dict keys so the populated dict is a different variable; switching code from forecast() to forecast_with_covariates() without passing actual covariates; future covariates available but not passed because of a merge/join failure.","solutions":["Pass at least one non-empty covariate dict to forecast_with_covariates","If you have no covariates, call `model.forecast(horizon, inputs)` instead","Add an assertion/check that the covariate dicts are non-empty before the call"],"exampleFix":"// before\nouts = model.forecast_with_covariates(horizon, inputs, freq, horizon_len,\n    dynamic_numerical_covariates={}, dynamic_categorical_covariates={})\n// after\nouts = model.forecast_with_covariates(horizon, inputs, freq, horizon_len,\n    dynamic_numerical_covariates={'temp': covariate_array})","handlingStrategy":"validation","validationCode":"covs = [dynamic_numerical_covariates, dynamic_categorical_covariates, static_numerical_covariates, static_categorical_covariates]\nif not any(c for c in covs):\n    raise ValueError('No covariates supplied; use model.forecast() instead of forecast_with_covariates()')","typeGuard":"def has_covariates(**kw) -> bool:\n    return any(kw.get(k) for k in ('dynamic_numerical_covariates','dynamic_categorical_covariates','static_numerical_covariates','static_categorical_covariates'))","tryCatchPattern":"try:\n    outputs = model.forecast_with_covariates(...)\nexcept ValueError as e:\n    if 'At least one of' in str(e):\n        outputs = model.forecast(horizon, inputs)  # fall back to plain forecasting\n    else:\n        raise","preventionTips":["Route to plain forecast() when covariate dicts are empty","Log a warning when covariate loading yields empty dicts (upstream data issue)","Validate covariate dicts are non-empty in the feature pipeline, before the model call"],"tags":["python","validation","covariates","empty-input"],"backgroundTag":"missing-required-argument","analyzedSha":"331c6d33cb1ac2611de3056d0ac7164aab6301eb","analyzedAt":"2026-08-29T01:04:23.138Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}