{"record":{"id":"3c760e21aa25698d","repo":"OpenBB-finance/OpenBB","slug":"expected-an-excelfile-object-got-type-file-ins","errorCode":null,"errorMessage":"Expected an ExcelFile object, got {type(file)} instead.","messagePattern":"Expected an ExcelFile object, got (.+?) instead\\.","errorType":"exception","errorClass":"OpenBBError","httpStatus":null,"severity":"error","filePath":"openbb_platform/providers/eia/openbb_us_eia/models/petroleum_status_report.py","lineNumber":160,"sourceCode":"        from functools import lru_cache\n        from numpy import nan\n        from pandas import Categorical, ExcelFile, concat, read_excel\n        from warnings import warn\n\n        category = query.category\n\n        _tables = (\n            query.table.split(\",\")  # type: ignore\n            if query.table\n            else [\"stocks\"] if category == \"weekly_estimates\" else [\"all\"]\n        )\n        all_tables = list(WpsrTableMap[category])\n        tables = all_tables if \"all\" in _tables else _tables\n\n        file = data.get(\"file\")\n\n        if not isinstance(file, ExcelFile):\n            raise OpenBBError(\n                TypeError(f\"Expected an ExcelFile object, got {type(file)} instead.\")\n            )\n\n        dfs: list = []\n\n        def replace_data_strings(text):\n            \"\"\"Replace the table strings with sortable numbers.\"\"\"\n            pattern = r\"Data (\\d):\"\n\n            def replacer(match):\n                \"\"\"Replace the matched string with a sortable number.\"\"\"\n                return f\"Data 0{match.group(1)}:\"\n\n            return re.sub(pattern, replacer, text)\n\n        @lru_cache(maxsize=128)\n        def read_excel_file(file, category, table):\n            \"\"\"Read the ExcelFile for the sheet name and flatten the table.\"\"\"","sourceCodeStart":142,"sourceCodeEnd":178,"githubUrl":"https://github.com/OpenBB-finance/OpenBB/blob/3e071fcc2cd9f891cac6040ae60296dba76dab46/openbb_platform/providers/eia/openbb_us_eia/models/petroleum_status_report.py#L142-L178","documentation":"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.","triggerScenarios":"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'].","commonSituations":"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.","solutions":["Don't call transform_data directly — use the Fetcher class or the OpenBB router so aextract_data runs first.","If you must build data manually, wrap bytes in ExcelFile(BytesIO(raw)) exactly like download_excel_file does.","Check that the extract step did not fail (error 325/332 conditions) before transform runs.","On exception, print type(file) to see what actually arrived."],"exampleFix":"# before\nresult = EiaPetroleumStatusReport.transform_data(query, {'file': raw_bytes})\n\n# after\nfrom io import BytesIO\nfrom pandas import ExcelFile\nresult = EiaPetroleumStatusReport.transform_data(query, {'file': ExcelFile(BytesIO(raw_bytes))})","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"from pandas import ExcelFile\n\ndef is_extracted_payload(data: dict) -> bool:\n    return isinstance(data, dict) and isinstance(data.get('file'), ExcelFile)","tryCatchPattern":"try:\n    out = EiaPetroleumStatusReport.transform_data(query, data)\nexcept OpenBBError as e:\n    if 'Expected an ExcelFile object' in str(e):\n        raise TypeError('transform_data requires the aextract_data payload') from e\n    raise","preventionTips":["Use the Fetcher/router so extract runs before transform","In tests, build payloads with ExcelFile(BytesIO(...)) to match the contract"],"tags":["eia","petroleum-status-report","type-guard","internal-contract"],"backgroundTag":null,"analyzedSha":"3e071fcc2cd9f891cac6040ae60296dba76dab46","analyzedAt":"2026-08-14T23:40:48.960Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}