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

  1. Use 'A' (annual), 'Q' (quarterly), or 'M' (monthly) — or words starting with those letters ('annual', 'quarterly', 'monthly').
  2. Map your internal frequency enum to IMFS vocabulary before calling: {'yearly':'A','quarterly':'Q','monthly':'M'}.
  3. 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

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


AI-assisted analysis of OpenBB-finance/OpenBB@3e071fcc2c (2026-08-14). Data as JSON: /api/errors/5a5b9018e14f1fa5. Report an issue: GitHub.