OpenBB-finance/OpenBB · error · OpenBBError

'vx_type' must be one of: 'am', 'eod'

Error message

'vx_type' must be one of: 'am', 'eod'

What it means

Same vx_type contract as the current-futures endpoint, but enforced in the historical VX futures path (vix.py:202) that queries CboeEquityHistoricalFetcher for one or more dates. 'eod' resolves symbols from get_vx_symbols(); 'am' uses the fixed VX_AM_SYMBOLS list. Any other value aborts before any network request is made.

Source

Thrown at openbb_platform/providers/cboe/openbb_cboe/utils/vix.py:202

            am: Mid-morning TWAP value
            eod: End-of-day value
    use_cache : bool
        Whether to use the cache. Default is True. Cache is only used for symbol mapping.

    Returns
    -------
    DataFrame
        Categorical DataFrame with VX futures data for the given date(s).
    """
    # pylint: disable=import-outside-toplevel
    from datetime import datetime, timedelta  # noqa
    from openbb_core.app.model.abstract.error import OpenBBError
    from openbb_core.provider.utils.errors import EmptyDataError
    from openbb_cboe.models.equity_historical import CboeEquityHistoricalFetcher
    from pandas import Categorical, DataFrame, DatetimeIndex, concat, isna, to_datetime

    if vx_type not in ["am", "eod"]:
        raise OpenBBError("'vx_type' must be one of: 'am', 'eod'")

    df = DataFrame()
    start_date = ""
    end_date = ""
    symbols = list(get_vx_symbols().values()) if vx_type == "eod" else VX_AM_SYMBOLS
    dates = date.split(",") if isinstance(date, str) else date
    dates = sorted([check_date(to_datetime(d)) for d in dates])
    today = check_date(datetime.today()).strftime("%Y-%m-%d")

    if len(dates) == 1:
        new_date = check_date(to_datetime(dates[0]))
        if new_date.strftime("%Y-%m-%d") == today:
            df = await get_vx_current(vx_type=vx_type)
            df["date"] = new_date.strftime("%Y-%m-%d")
            return df

        end_date = new_date.strftime("%Y-%m-%d")
        start_date = (check_date(new_date - timedelta(days=1))).strftime("%Y-%m-%d")

View on GitHub (pinned to 3e071fcc2c)

Solutions

  1. Use lowercase 'am' or 'eod' for vx_type.
  2. Sanitize at the boundary: assert vx_type in ('am', 'eod') before invoking the helper.
  3. Define the parameter as Literal['am', 'eod'] in your own wrapper so mypy/pydantic reject bad values early.

Example fix

# before
df = await get_vx_futures_historical(date='2024-01-15', vx_type='EOD')

# after
df = await get_vx_futures_historical(date='2024-01-15', vx_type='eod')
Defensive patterns

Strategy: validation

Validate before calling

assert date is not None, 'date is required for historical VX futures'
vx_type = vx_type.strip().lower()
if vx_type not in ('am', 'eod'):
    raise ValueError("vx_type must be 'am' or 'eod'")

Type guard

def is_vx_type(value: str) -> bool:
    return isinstance(value, str) and value.strip().lower() in ('am', 'eod')

Prevention

When it happens

Trigger: Calling the historical VX futures helper with vx_type='AM'/'EOD'/'spot'/None, or forwarding an unvalidated CLI/web form field straight into the function alongside a date or comma-separated date list.

Common situations: Case-mismatch from UI labels; copy-pasting parameter values from docs that capitalize words in prose; automated pipelines that derive vx_type from a filename or config key with different casing.

Related errors


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