OpenBB-finance/OpenBB · error · ValueError
Invalid extension type(s): {', '.join(invalid)}. Valid choic
Error message
Invalid extension type(s): {', '.join(invalid)}. Valid choices: {', '.join(VALID_EXTENSION_TYPES)} What it means
Raised at market_snapshots.py:195 inside get_csv() when the CSV fetched from a snapshot file URL produces an empty pandas DataFrame. Two paths reach it: (a) the response body was not `bytes` (e.g. an HTML/JSON error page, a dict from an error handler), so `df` stays the empty DataFrame initialized on line 190; or (b) the body was bytes but decompressed/parsed to zero rows. Since asyncio.gather runs get_csv over every file URL concurrently, one bad file fails the whole request.
Source
Thrown at cookiecutter/openbb_cookiecutter/cli.py:27
from rich.prompt import Prompt
from . import get_template_path
VALID_EXTENSION_TYPES = [
"router",
"provider",
"obbject",
"on_command_output",
"charting",
"all",
]
def _parse_extension_types(value: str) -> list[str]:
types = [t.strip() for t in value.split(",") if t.strip()]
invalid = [t for t in types if t not in VALID_EXTENSION_TYPES]
if invalid:
raise ValueError(
f"Invalid extension type(s): {', '.join(invalid)}. "
f"Valid choices: {', '.join(VALID_EXTENSION_TYPES)}"
)
if not types:
raise ValueError("At least one extension type must be selected.")
return types
def _prompt_context(preset_extension_types: list[str] | None = None) -> dict:
context = {}
context["full_name"] = Prompt.ask(" full_name", default="Hello World")
context["email"] = Prompt.ask(" email", default="hello@world.com")
context["project_name"] = Prompt.ask(
" project_name", default="OpenBB Python Extension Template"
)
default_tag = context["project_name"].lower().replace(" ", "-").replace("_", "-")
context["project_tag"] = Prompt.ask(" project_tag", default=default_tag)View on GitHub (pinned to 3e071fcc2c)
Solutions
- Retry the request end-to-end — the snapshots listing and file URLs are fetched fresh each call, which replaces any expired signed URLs.
- Fetch the URL from the erroring file directly (extract snapshots[].files[].url via curl) to see whether the file is genuinely empty or returns an auth/expiry error; if genuinely empty, it is an Intrinio-side issue — report it.
- If it recurs for a specific date, request a slightly different datetime (e.g. 30 minutes earlier) to get a different snapshot file set.
- Update the provider package (pip install -U openbb-intrinio) in case handling of non-gzip responses was fixed after your version.
- Handle transient CDN failures in your own code with a retry/backoff around the whole obb.equity.market_snapshots call.
Example fix
# before
res = obb.equity.market_snapshots(provider='intrinio') # one empty file kills whole request via asyncio.gather
# after
from openbb_core.app.model.abstract.error import OpenBBError
for attempt in range(3):
try:
res = obb.equity.market_snapshots(provider='intrinio')
break
except OpenBBError as e:
if 'Empty CSV file' in str(e) and attempt < 2:
continue
raise Defensive patterns
Strategy: retry
Validate before calling
// not applicable - the empty file is served by Intrinio/S3 and cannot be inspected before the library fetches it; only a retry with a fresh snapshots listing (new signed URLs) helps
Type guard
def is_empty_csv_error(exc: Exception) -> bool:
"""True when a snapshot CSV file came back empty or unparseable."""
return isinstance(exc, OpenBBError) and 'Empty CSV file' in str(exc) Try / catch
from openbb_core.app.model.abstract.error import OpenBBError
import asyncio
async def snapshots_with_retry(attempts: int = 3):
for i in range(attempts):
try:
return await obb.equity.market_snapshots(provider='intrinio')
except OpenBBError as e:
if 'Empty CSV file' in str(e) and i < attempts - 1:
await asyncio.sleep(2 ** i) # signed URL expiry / transient S3 issue
continue
raise Prevention
- Do not cache the intermediate snapshots listing (file URLs) — always re-request it in the same run so signed URLs are fresh.
- Add retry with backoff around the whole market_snapshots call for transient empty-file/CDN failures.
- If a specific datetime repeatedly fails, shift the requested datetime slightly to receive a different file set.
- Keep openbb-intrinio updated so fixes to non-gzip or error-body responses are picked up.
When it happens
Trigger: Calling `equity.market_snapshots(provider='intrinio')` where at least one snapshot CSV URL returned via response_callback is empty, expired (the signed S3 URLs in the snapshots response are short-lived), redirected to an error body, or served uncompressed/non-gzip content that gzip.decompress would reject. df.empty is also true when read_csv yields only headers with no rows.
Common situations: Reusing a cached/stale snapshots response whose file URLs have expired; transient S3/CDN issue returning an empty or error body; Intrinio snapshot generation producing an empty file for part of the day; race where the snapshot file is still being written; proxy/antivirus stripping the response body.
Related errors
- Unsupported file format. Please use .json or .env files.
- Failed to get Jupyter URL
- Error requesting dates. Please try again later.
- No data found. Try again later.
- At least one extension type must be selected.
AI-assisted analysis of OpenBB-finance/OpenBB@3e071fcc2c (2026-08-14).
Data as JSON: /api/errors/bcdcae4ef60362b4.
Report an issue: GitHub.