Series-level metadata for WEO releases, and two consistency fixes in the call that merges it onto observations.
Series metadata
Every uncached WEO fetch already downloads a per-series sidecar, 8,200 rows by 49 columns against the April 2026 release. Six of those columns were surfaced. The rest are now readable.
from imf_reader import weo
meta = weo.fetch_series_metadata() # (8200, 41), one row per series
merged = weo.fetch_data_with_metadata() # (361733, 54), observations plus metadataweo.fetch_series_metadata(version=None) returns the metadata on its own, keyed on REF_AREA_CODE, CONCEPT_CODE and FREQ_CODE. weo.fetch_data_with_metadata(version=None) returns the two merged, resolving both halves to one release. weo.api.get_series_metadata(version=None) is the api-layer equivalent. weo.SERIES_METADATA_JOIN_KEYS names the join keys for callers merging by hand.
The new columns carry the SDMX classification codes that link a series to the IMF's codelists (NA_STO, GFS_STO, SECTOR, PRICES) along with SERIES_NAME, METHODOLOGY, BASE_YEAR, BASIS_OF_PROJECTIONS and START_END_MONTHS_OF_REPORTING_YEAR. That last one, plus the raw LATEST_ACTUAL_ANNUAL_DATA with its FY2023/24 forms intact, closes the fiscal-year gap the v2.1.0 notes recorded under "Known gotchas". LASTACTUALDATE collapses those forms to a leading year.
fetch_data's 16 columns are unchanged, so this is additive.
Series metadata covers April 2025 onward, the releases the IMF API itself serves. The bulk archive that serves earlier releases carries none of these attributes, so a version the API can't serve raises VersionNotAvailableError.
Fixes
fetch_data_with_metadata reads the sidecar twice per call, which left two ways for its halves to disagree. It now pins its metadata leg to the FlowRef that served its observations leg, closing a window where the hour-long flow-mapping cache could remap the release between the two. It also rebuilds LASTACTUALDATE, NOTES and COUNTRY_UPDATE_DATE when a transient sidecar failure left them null and a later read of the same cache succeeded.
A sidecar cell whose literal content is N/A was read as null, indistinguishable from a genuinely empty cell. pandas.read_csv's default NA-token list was catching values the IMF publishes, 19 cells across METHODOLOGY_NOTES and BASIS_OF_PROJECTIONS in the April 2026 release. fetch_series_metadata() now preserves the literal. fetch_data's derived NOTES column still reads both forms as null, since null is the right value for "no note" there.
Upgrading
No code changes required. The cached sidecar's schema discriminator moved, so the first call after upgrading re-fetches the sidecar rather than serving a warm 7-day parquet written under the old read.
Full detail in CHANGELOG.md and the WEO docs.