{"record":{"id":"cb4c22ca5b044795","repo":"OpenBB-finance/OpenBB","slug":"symbol-is-required","errorCode":null,"errorMessage":"Symbol is required.","messagePattern":"Symbol is required\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"openbb_platform/providers/deribit/openbb_deribit/models/futures_historical.py","lineNumber":51,"sourceCode":"    }\n\n    interval: DeribitIntervals = Field(\n        default=\"1d\", description=QUERY_DESCRIPTIONS.get(\"interval\", \"\")\n    )\n\n    @field_validator(\"symbol\", mode=\"before\", check_fields=False)\n    @classmethod\n    def _validate_symbol(cls, v):\n        \"\"\"Validate the symbol.\"\"\"\n        # pylint: disable=import-outside-toplevel\n        from openbb_core.provider.utils.helpers import run_async\n        from openbb_deribit.utils.helpers import (\n            get_futures_symbols,\n            get_perpetual_symbols,\n        )\n\n        if not v:\n            raise ValueError(\"Symbol is required.\")\n\n        futures_symbols = run_async(get_futures_symbols)\n        perpetual_symbols = run_async(get_perpetual_symbols)\n        all_symbols = list(perpetual_symbols) + futures_symbols\n        symbols = v.upper().split(\",\")\n        new_symbols: list = []\n\n        for symbol in symbols:\n            if symbol not in all_symbols:\n                raise ValueError(\n                    f\"Invalid Deribit symbol: {symbol}. Supported symbols are: {', '.join(all_symbols)}\"\n                )\n            if symbol in perpetual_symbols:\n                new_symbols.append(perpetual_symbols[symbol])\n            else:\n                new_symbols.append(symbol)\n\n        return \",\".join(new_symbols)","sourceCodeStart":33,"sourceCodeEnd":69,"githubUrl":"https://github.com/OpenBB-finance/OpenBB/blob/3e071fcc2cd9f891cac6040ae60296dba76dab46/openbb_platform/providers/deribit/openbb_deribit/models/futures_historical.py#L33-L69","documentation":"The DeribitFuturesHistoricalQueryParams symbol validator first rejects an empty value, then synchronously fetches the complete live symbol universe from Deribit (futures + perpetuals via run_async) and rejects any symbol not in it. This makes validation network-dependent: it fails both on empty input and on any instrument not currently listed, and it can be slow. The ValueError comes from pydantic field validation.","triggerScenarios":"symbol='' (empty) — the direct trigger for 'Symbol is required.'; expired futures like 'BTC-27SEP24' no longer listed; typo'd instrument names; lowercase input is fine (uppercased) but hyphen/spacing variants must exactly match Deribit naming (e.g. 'BTC-PERPETUAL', 'ETH-27JUN25').","commonSituations":"Passing expired contract symbols after rollover; hardcoded instrument names in production code aging out; symbol lists built from other exchanges; calls during Deribit API downtime where the symbol fetch itself errors.","solutions":["Pass a non-empty, currently listed Deribit instrument name, e.g. 'BTC-PERPETUAL' or 'ETH-27JUN25'","Refresh the valid universe programmatically first: from openbb_deribit.utils.helpers import get_futures_symbols; valid = await get_futures_symbols()","For backfills on expired contracts, note the validator only knows live listings — pin a package version or use Deribit's API directly for delisted instruments"],"exampleFix":"# before\nhist = obb.derivatives.futures.historical(symbol='BTC-27SEP24', provider='deribit')  # expired\n\n# after\nfrom openbb_deribit.utils.helpers import get_futures_symbols\nvalid = await get_futures_symbols()\nsym = next(s for s in valid if s.startswith('BTC-2'))  # pick a live dated future\nhist = obb.derivatives.futures.historical(symbol=sym, provider='deribit')","handlingStrategy":"validation","validationCode":"from openbb_deribit.utils.helpers import get_futures_symbols, get_perpetual_symbols\n\nasync def assert_live_symbol(symbol: str) -> str:\n    s = symbol.strip().upper()\n    universe = set(await get_perpetual_symbols()) | set(await get_futures_symbols())\n    if s not in universe:\n        raise ValueError(f'{s!r} not currently listed on Deribit')\n    return s","typeGuard":"async def is_live_deribit_symbol(symbol: str) -> bool:\n    s = symbol.strip().upper()\n    universe = set(await get_perpetual_symbols()) | set(await get_futures_symbols())\n    return s in universe","tryCatchPattern":"try:\n    hist = obb.derivatives.futures.historical(symbol=sym, provider='deribit')\nexcept ValueError as e:\n    if 'Symbol is required' in str(e):\n        raise  # caller bug: empty symbol\n    if 'Invalid Deribit symbol' in str(e):\n        sym = 'BTC-PERPETUAL'  # fall back to a always-listed instrument\n        hist = obb.derivatives.futures.historical(symbol=sym, provider='deribit')\n    else:\n        raise","preventionTips":["Never pass empty symbol strings — guard at the call site","Refresh the symbol universe each run; validators only know live listings, so expired contracts fail","Note this validation makes a network call per instantiation — cache the symbol set for batch jobs"],"tags":["deribit","validation","symbol","expired-contract","pydantic"],"backgroundTag":null,"analyzedSha":"3e071fcc2cd9f891cac6040ae60296dba76dab46","analyzedAt":"2026-08-14T23:40:48.960Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}