OpenBB-finance/OpenBB · error · OpenBBError
Last price must be provided for options filtering, and was…
Error message
Last price must be provided for options filtering, and was not found in the data.
What it means
Raised by the options processing/filtering helper when the resolved last_price is None. The value comes from 'underlying_price or options.underlying_price.iloc[0]' - so it fires when no underlying_price argument was passed AND the first row of the DataFrame's underlying_price column is None. Moneyness filtering needs the spot, so it aborts.
Solutions
- Pass underlying_price explicitly to the call.
- Backfill the column before processing: df['underlying_price'] = df['underlying_price'].ffill().bfill().fillna(spot).
- Use a provider/date combination that returns a populated underlying_price.
- Pre-validate: v = df.get('underlying_price'); require v is not None and not pd.isna(v.iloc[0]).
Example fix
# before res = process_options(data=df, moneyness=5) # underlying_price.iloc[0] is None # after res = process_options(data=df, moneyness=5, underlying_price=spot)
Defensive patterns
Strategy: validation
Validate before calling
import pandas as pd
col = df.get('underlying_price')
if underlying_price is None:
if col is None or col.empty or col.iloc[0] is None or pd.isna(col.iloc[0]):
raise ValueError('underlying_price unavailable; pass it explicitly') Type guard
def has_spot(df, underlying_price=None) -> bool:
import pandas as pd
if underlying_price:
return True
col = df.get('underlying_price')
return col is not None and not col.empty and col.iloc[0] is not None and not pd.isna(col.iloc[0]) Try / catch
try:
res = process_options(data=df, moneyness=5)
except OpenBBError as e:
if 'Last price must be provided' in str(e):
res = process_options(data=df, moneyness=5, underlying_price=get_spot(symbol)) Prevention
- Pass underlying_price explicitly whenever moneyness filtering is requested.
- Backfill/fill the underlying_price column at ingestion time.
- Note NaN spot values pass the None check but poison downstream math - scrub both None and NaN.
When it happens
Trigger: Calling the options filter/processing helper with moneyness filtering on data where the underlying_price column exists but its first value is None (dumped with exclude_none semantics), and no underlying_price argument supplied. Note NaN passes this check (NaN is not None) and fails differently downstream.
Common situations: Providers that include the underlying_price field but leave it None on some rows; historical/EOD payloads missing the spot; user-constructed DataFrames where the column was added but never filled.
Related errors
- Error: No premium data found for the selected strikes. Call
- Error: No premium data found for the selected strikes. Call
- Error: Not enough information to complete the operation…
- Error: Not enough information to complete the operation…
- Error: Data is a required field.
AI-assisted analysis of OpenBB-finance/OpenBB@3e071fcc2c (2026-08-14).
Data as JSON: /api/errors/73631477c318843d.
Report an issue: GitHub.
Appendix: source
Thrown at openbb_platform/extensions/derivatives/openbb_derivatives/options/options_router.py:166
if isinstance(data, OptionsChainsData):
df = data.dataframe
elif isinstance(data, DataFrame):
df = data
elif isinstance(data, dict) and all(isinstance(v, list) for v in data.values()):
df = DataFrame(data)
elif isinstance(data, list):
if all(isinstance(d, dict) for d in data):
df = DataFrame(data)
elif all(isinstance(d, Data) for d in data):
df = DataFrame([d.model_dump(exclude_none=True, exclude_unset=True) for d in data]) # type: ignore
options = DataFrame(df.copy())
last_price = underlying_price or options.underlying_price.iloc[0] # type: ignore
if last_price is None:
raise OpenBBError(
ValueError(
"Last price must be provided for options filtering, and was not found in the data."
)
)
if target not in options.columns: # type: ignore
raise OpenBBError(f"Error: No {target} field found.")
if "dte" not in options.columns: # type: ignore
options.dte = (options.expiration - datetime.today().date()).days # type: ignore
calls = options.query(f"`option_type` == 'call' and `dte` >= 0 and `{target}` > 0") # type: ignore
puts = options.query(f"`option_type` == 'put' and `dte` >= 0 and `{target}` > 0") # type: ignore
if oi:
calls = calls[calls["open_interest"] > 0]
puts = puts[puts["open_interest"] > 0]
if volume:View on GitHub (pinned to 3e071fcc2c)