Troubleshooting & FAQ
When a macroforecast recipe / API call fails, walk through these checks before filing an issue. Most failures hit one of the patterns below.
Recipe fails immediately at L1
RuntimeError: cell cell_001 failed: single_target requires leaf_config.target string
Cause: L1 target_structure=single_target (the default) but
leaf_config.target is missing.
Fix: add leaf_config.target: <column_name> under 1_data in your
recipe. For inline panels, the column name must exist in
custom_panel_inline.
1_data:
fixed_axes: {target_structure: single_target}
leaf_config:
target: INDPRO # required
target_horizons: [1, 3, 6] # required when horizon_set != standard_*
pip install macroforecast installs a version older than 0.6
You’re probably hitting the older macroforecast 0.1.0 artifact (a
maintainer-uploaded placeholder before the v0.6 series). Upgrade:
pip install --upgrade macroforecast
python -c "import macroforecast; print(macroforecast.__version__)"
Should print 0.8.6 or later. If it still shows 0.1.0, you have a
stale cached install — pip install --force-reinstall macroforecast.
compare_models([...]).compare(...) doesn’t find the L4 fit node
Symptom:
exp.compare_models(["ridge", "lasso"]).compare(
"4_forecasting_model.nodes.fit_main.params.alpha", [0.1, 1.0]
)
works on v0.8.6+. On v0.8.0 / v0.8.5 the L4 fit node had
auto-generated id fit_1_<family> (e.g. fit_1_ridge), so chained
.compare() calls broke.
Fix: upgrade to v0.8.6+ where fit_main is the stable id, OR use
the auto-generated id explicitly. Verify with:
print(exp.to_recipe_dict()["4_forecasting_model"]["nodes"])
mf.replicate(manifest_path).sink_hashes_match is False
Bit-exact replication is guaranteed only when:
same package version (manifest carries the macroforecast version it was produced with).
same dependency versions (lockfile pinned: pandas / numpy / scikit-learn / statsmodels / scipy).
same recipe (the manifest stores the canonical-key-ordered recipe; replicate compares
recipe_match=Truefirst).same raw data / cache (FRED data revisions break the contract; pin the cache via
cache_root=and re-use across runs).deterministic model families — torch / xgboost / lightgbm / catboost may introduce nondeterminism on GPU / threaded backends. CPU
single-thread is the deterministic baseline.
Debug:
replication = mf.replicate("out/manifest.json")
print("recipe_match:", replication.recipe_match)
for cell_id, ok in replication.per_cell_match.items():
print(f" {cell_id}: {ok}")
If recipe_match=False, the recipe was edited after the manifest was
written. If per_cell_match[<cell_id>]=False, that specific cell’s
sink hashes drifted — check the original cell’s sink_hashes against
the new run’s.
Custom preprocessor / model not registered
RuntimeError: custom callable 'my_preproc' not registered
Cause: the decorator (@mf.custom_preprocessor("my_preproc")) ran
in a Python process / session different from the one that calls
Experiment.run(). macroforecast looks up callables by name in the
in-process registry.
Fix: import the module that defines the callable in the same
process before calling run():
import my_methods # the file with @mf.custom_preprocessor decorators
import macroforecast as mf
exp = mf.Experiment(...).use_preprocessor("my_preproc")
exp.run()
For batch / CI runs, ensure the recipe runner imports your method
module before calling mf.run("recipe.yaml"). See
docs/for_recipe_authors/custom_hooks.md
for the full registration contract.
mixed_frequency_representation gate doesn’t fire
The axis is gated: it is only active when L1 produces a mixed-frequency panel. Triggers:
datasetincludesfred_sd(e.g.fred_md+fred_sd).A custom panel inlines mixed monthly + quarterly columns and L1 has detected it.
If your dataset=fred_md and you set
mixed_frequency_representation=..., the validator emits a soft
warning and the axis is ignored.
A bundled example recipe fails with ImportError: xgboost
Some recipes need extras. Check the Recipe gallery “Extras required” column. To install everything:
pip install "macroforecast[all]"
Or specific extras:
pip install "macroforecast[xgboost,lightgbm,catboost,shap]"
Sphinx encyclopedia drift CI fails on PR
docs/encyclopedia/ is out of sync. Run: python -m macroforecast.scaffold encyclopedia docs/encyclopedia/
You edited a LayerImplementationSpec axis or an OPTION_DOCS entry,
and the encyclopedia source-committed tree no longer matches the
generator output.
Fix:
python -m macroforecast.scaffold encyclopedia docs/encyclopedia/
git add docs/encyclopedia/
git commit -m "docs(encyclopedia): regen after axis/OptionDoc edit"
Want to inspect L1 / L2 / L3 outputs without running L4-L8
from macroforecast.core import materialize_l1, materialize_l2, materialize_l3_minimal
from macroforecast.core.yaml import parse_recipe_yaml
recipe = parse_recipe_yaml(open("recipe.yaml").read())
l1 = materialize_l1(recipe)
print(l1[0].raw_panel.head()) # raw L1 panel
l2, _ = materialize_l2(recipe, l1[0])
print(l2.cleaned_panel.head()) # post-McCracken-Ng panel
print(l2.cleaning_log["steps"]) # which stages applied what
l3 = materialize_l3_minimal(recipe, l1[0], l2)
print(l3[0].X_final.head()) # L3 features
print(l3[0].y_final.head()) # L3 target
Full guide:
docs/for_recipe_authors/partial_layer_execution.md.
Where to ask
GitHub issues — bugs / feature requests
GitHub discussions — recipe / method questions
Include in your report: macroforecast
__version__, Python version, the recipe (or a minimal repro), the full traceback, and what you expected.