OpenBB-finance/OpenBB · error · ValueError
Frequency must be one of 'A', 'Q', or 'M'.
Error message
Frequency must be one of 'A', 'Q', or 'M'.
What it means
imts_query only accepts annual ('A'), quarterly ('Q'), or monthly ('M') frequencies because those are the only periods the IMTS dataflow publishes. The code takes freq[0].upper() — so the first character decides — and rejects anything whose first letter is not A/Q/M. Full words like 'annual' work ('a'->'A'), but 'weekly', 'daily', 'W', 'D' fail.
Source
Thrown at openbb_platform/providers/imf/openbb_imf/utils/dot_helpers.py:170
**kwargs : dict
Additional query parameters to pass to the API.
Returns
-------
dict
A dictionary with keys: 'data' containing the fetched data,
and 'metadata' containing the related metadata.
"""
# pylint: disable=import-outside-toplevel
from openbb_imf.utils.query_builder import ImfQueryBuilder
if not country or not counterpart:
raise ValueError("Country and counterpart parameters cannot be empty.")
freq = freq[0].upper()
if freq and freq not in ["A", "Q", "M"]:
raise ValueError("Frequency must be one of 'A', 'Q', or 'M'.")
query_builder = ImfQueryBuilder()
dataflow_id = "IMTS"
params = query_builder.metadata.get_dataflow_parameters(dataflow_id)
country_values = {item["value"] for item in params.get("COUNTRY", [])}
counterpart_values = {
item["value"]
for item in params.get("COUNTERPART_COUNTRY", params.get("COUNTRY", []))
}
def _validate_selection(selection, valid_values, name):
"""Validate country or counterpart selection."""
if not valid_values:
return selection
# Handle wildcards - return "*" as-is
if selection == "*":
return "*"View on GitHub (pinned to 3e071fcc2c)
Solutions
- Use 'A' (annual), 'Q' (quarterly), or 'M' (monthly) — or words starting with those letters ('annual', 'quarterly', 'monthly').
- Map your internal frequency enum to IMFS vocabulary before calling: {'yearly':'A','quarterly':'Q','monthly':'M'}.
- Remember only the first character is inspected, so avoid multi-char codes entirely.
Example fix
# before res = imts_query(country='USA', counterpart='DEU', indicator='TXG_FOB_USD', freq='W') # after res = imts_query(country='USA', counterpart='DEU', indicator='TXG_FOB_USD', freq='M')
Defensive patterns
Strategy: validation
Validate before calling
FREQ_MAP = {'A': 'A', 'Q': 'Q', 'M': 'M',
'Y': 'A', 'ANNUAL': 'A', 'YEARLY': 'A',
'QUARTERLY': 'Q', 'MONTHLY': 'M'}
freq = FREQ_MAP.get(freq.strip().upper())
if freq is None:
raise ValueError(f"Unsupported frequency; use one of A/Q/M (got {freq!r}).") Type guard
def is_imts_freq(freq: str | None) -> bool:
return freq is None or (isinstance(freq, str) and freq[:1].upper() in {'A', 'Q', 'M'}) Try / catch
try:
res = imts_query(country=c, counterpart=cp, indicator=ind, freq=freq)
except ValueError as e:
if 'Frequency must be' in str(e):
res = imts_query(country=c, counterpart=cp, indicator=ind, freq='A')
else:
raise Prevention
- Map your app's frequency enum to A/Q/M at the boundary.
- Note only freq[0] is inspected — 'annual' passes, 'yearly' fails.
- Never forward FRED-style codes ('Q', ok) vs ('W', 'D' fail) blindly.
When it happens
Trigger: freq='W', freq='daily' ('d'), freq='weekly' ('w'), or a freq string copied from another provider's vocabulary (e.g. 'B' for business from FRED-style APIs).
Common situations: Reusing a frequency parameter across multiple providers in one script; new users guessing 'Y' for yearly instead of 'A'; passing pandas offset aliases ('QS', 'ME').
Related errors
- Country value cannot be empty.
- Country '{value}' is not a valid IMF country code or country
- Country and counterpart parameters cannot be empty.
- Chart not found.
- No valid port_code provided.
AI-assisted analysis of OpenBB-finance/OpenBB@3e071fcc2c (2026-08-14).
Data as JSON: /api/errors/5a5b9018e14f1fa5.
Report an issue: GitHub.