OpenBB-finance/OpenBB · error · OpenBBError

Expected an ExcelFile object, got {type(file)} instead.

Error message

Expected an ExcelFile object, got {type(file)} instead.

What it means

Transform-stage type guard in the EIA Petroleum Status Report model: transform_data expects the data dict to contain an openpyxl/pandas 'ExcelFile' object produced by aextract_data. If data['file'] is anything else (None, bytes, a DataFrame), this TypeError is wrapped in OpenBBError. In practice it signals a broken extract stage or direct misuse of transform_data with raw data.

Source

Thrown at openbb_platform/providers/eia/openbb_us_eia/models/petroleum_status_report.py:160

        from functools import lru_cache
        from numpy import nan
        from pandas import Categorical, ExcelFile, concat, read_excel
        from warnings import warn

        category = query.category

        _tables = (
            query.table.split(",")  # type: ignore
            if query.table
            else ["stocks"] if category == "weekly_estimates" else ["all"]
        )
        all_tables = list(WpsrTableMap[category])
        tables = all_tables if "all" in _tables else _tables

        file = data.get("file")

        if not isinstance(file, ExcelFile):
            raise OpenBBError(
                TypeError(f"Expected an ExcelFile object, got {type(file)} instead.")
            )

        dfs: list = []

        def replace_data_strings(text):
            """Replace the table strings with sortable numbers."""
            pattern = r"Data (\d):"

            def replacer(match):
                """Replace the matched string with a sortable number."""
                return f"Data 0{match.group(1)}:"

            return re.sub(pattern, replacer, text)

        @lru_cache(maxsize=128)
        def read_excel_file(file, category, table):
            """Read the ExcelFile for the sheet name and flatten the table."""

View on GitHub (pinned to 3e071fcc2c)

Solutions

  1. Don't call transform_data directly — use the Fetcher class or the OpenBB router so aextract_data runs first.
  2. If you must build data manually, wrap bytes in ExcelFile(BytesIO(raw)) exactly like download_excel_file does.
  3. Check that the extract step did not fail (error 325/332 conditions) before transform runs.
  4. On exception, print type(file) to see what actually arrived.

Example fix

# before
result = EiaPetroleumStatusReport.transform_data(query, {'file': raw_bytes})

# after
from io import BytesIO
from pandas import ExcelFile
result = EiaPetroleumStatusReport.transform_data(query, {'file': ExcelFile(BytesIO(raw_bytes))})
Defensive patterns

Strategy: type-guard

Type guard

from pandas import ExcelFile

def is_extracted_payload(data: dict) -> bool:
    return isinstance(data, dict) and isinstance(data.get('file'), ExcelFile)

Try / catch

try:
    out = EiaPetroleumStatusReport.transform_data(query, data)
except OpenBBError as e:
    if 'Expected an ExcelFile object' in str(e):
        raise TypeError('transform_data requires the aextract_data payload') from e
    raise

Prevention

When it happens

Trigger: Calling EiaPetroleumStatusReport.transform_data directly with a hand-built dict; a mocked/test extract that returned bytes instead of ExcelFile; the download step silently returning an error payload that got stuffed into data['file'].

Common situations: Writing unit tests that fake extract data incorrectly; refactoring the extract/transform pipeline and changing the intermediate contract; upstream changes to download_excel_file's return type.

Related errors


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