Skip to content

Fix data refresh crash: US CPI 2026-10 has no 2025-10 counterpart - #235

Merged
vahid-ahmadi merged 1 commit into
mainfrom
vahid/fix-us-cpi-missing-year-ago
Nov 11, 2026
Merged

vahid-ahmadi merged 1 commit into
mainfrom
vahid/fix-us-cpi-missing-year-ago

Conversation

@vahid-ahmadi

Copy link
Copy Markdown
Contributor

Cause

The scheduled Fetch data vintages run 42980628369 (main e84d8c19) stopped at the pages step:

$ python3 economy/topics.py
  File "economy/topics.py", line 2290, in us_inflation_note
    change = 100 * (now["value"] / year_ago["value"] - 1)
TypeError: 'NoneType' object is not subscriptable
FAILED (1): python3 economy/topics.py

The same run's fetch step shows written us_cpi: FRED published the 2026-10 CPIAUCSL index (337.476). year_earlier() looks for 2025-10, and the store has no such row. That is not a fetch bug: FRED itself publishes no value for that month. The row is blank in the source CSV:

$ curl -s 'https://fred.stlouisfed.org/graph/fredgraph.csv?id=CPIAUCSL&cosd=2025-08-01'
2025-09-01,324.245
2025-10-01,
2025-11-01,325.063

fetch.py drops the blank, as intended. The recovered vintages (#234) are not involved. This is the first month whose year-earlier counterpart is that hole, so it surfaced only now. It recurs only for 2026-10: from 2026-11 every month has a counterpart again.

Three places were affected, not one:

  • us_inflation_note crashed (the failure above).
  • stat_card(us_cpi, "yoy") would have raised RuntimeError next.
  • us_inflation_hook printed the 2026-09 rate beside the 2026-10 index, because yoy() skips 2026-10 but the hook took latest().

Fix

  • New latest_year_on_year(series) returns the newest observation that has a counterpart a year earlier, that counterpart, and any newer observations that have none.
  • The US inflation note, hook and card, and the US growth note, use it. Where the newest month has no counterpart, the page says so: "The newest stored month, 2026-10, has no year-on-year rate here: the store holds no 2025-10 observation to compare it with, and none is interpolated." No number is derived for 2026-10 from any other month.
  • movement(): from 2026-11 the "prior month" rate would really be 2026-09's. The text now names that comparison, against 2026-09, the latest earlier rate (2026-10 has none), instead of calling it "the prior month".
  • When every month has a counterpart, the output is byte-identical: python3 economy/topics.py --check passes against main's committed pages.

Tests

tests/test_topics_year_on_year.py uses a synthetic series with the same hole, because main's data ends at 2026-09 and a test reading the store would pass before the fix.

  • On main (before): 7 of 8 fail. The note test fails with the production TypeError, the card test with RuntimeError, and the hook test because the hook pairs the wrong index.
  • On this branch: 8 of 8 pass.

Pipeline check. The full pipeline ran locally on today's real data: data/fetch.py at about 10:03 UTC wrote us_cpi 2026-10, then data/refresh.py --carry-from data/vintage-refresh --skip-fetch ran with this fix.

  • Every step and every gate passed: pytest tests gave 3219 passed and 87 skipped, and the append-only check passed.
  • None of that fetched data is committed here. This PR changes only economy/topics.py and the new test file.

Once this merges, dispatching Fetch data vintages on main rebuilds #195.

🤖 Generated with Claude Code

…part

FRED publishes no CPIAUCSL value for 2025-10, so when the October 2026
index arrived on 11 Nov, us_inflation_note looked up a year-earlier row that
does not exist and economy/topics.py crashed with a TypeError, stopping the
whole data refresh (run 42980628369). The card would have raised next, and
the hook printed the 2026-09 rate beside the 2026-10 index.

The note, hook, card and US growth note now use the newest month that has
a counterpart and say plainly that the newer month has none; nothing is
interpolated. movement() names the comparison when the previous month has
no rate instead of calling it "the prior month". Output is byte-identical
when every month has a counterpart (topics.py --check passes on main).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@vahid-ahmadi
vahid-ahmadi marked this pull request as ready for review November 11, 2026 10:24
@vahid-ahmadi
vahid-ahmadi merged commit 439576b into main Nov 11, 2026
6 checks passed

This branch was successfully deployed

1 active deployment
Preview — 61dafa80 Deployed Nov 11, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant