OpenBB-finance/OpenBB · error · ValueError
Failed to convert dictionary of lists to list of records
Error message
Failed to convert dictionary of lists to list of records
What it means
Thrown by the OmniWidgetResponseModel model_validator when content is a dict whose values are all lists (the column->list table shape) but building a DataFrame from it and serializing to records fails. This is the dict-of-lists table conversion path; failures are chained into this ValueError.
Source
Thrown at openbb_platform/extensions/platform_api/openbb_platform_api/response_models.py:262
isinstance(item, dict) for item in content
):
values.parse_as = "table"
elif isinstance(content, pd.DataFrame):
values.parse_as = "table"
try:
content = json.loads(content.to_json(orient="records"))
except Exception as e:
raise ValueError("Failed to convert DataFrame to JSON") from e
values.content = content
elif isinstance(content, dict) and all(
isinstance(v, list) for v in content.values()
):
values.parse_as = "table"
try:
df = pd.DataFrame(content)
content = json.loads(df.to_json(orient="records"))
except Exception as e:
raise ValueError(
"Failed to convert dictionary of lists to list of records"
) from e
values.content = content
elif isinstance(content, str) and content.strip(): # pylint: disable=R0916
try:
content = json.loads(content)
except json.JSONDecodeError:
# Remove trailing commas in objects and arrays
try:
cleaned_content = re.sub(r",(\s*[}\]])", r"\1", content)
content = json.loads(cleaned_content)
except json.JSONDecodeError:
pass
values.parse_as = "table" if isinstance(content, (list, dict)) else "text"
values.content = content
else:
values.parse_as = "text"View on GitHub (pinned to 3e071fcc2c)
Solutions
- Verify all value lists have equal length: assert len({len(v) for v in content.values()}) == 1.
- Coerce non-serializable elements to primitives (str/float/int) before constructing the model.
- Build the records list yourself (list(zip(...)) -> list of dicts) and pass it as content so the list-of-dicts branch is used.
- Check e.__cause__ for the exact pandas error (usually 'All arrays must be of the same length').
Example fix
# before
content = {"a": [1, 2], "b": [3]} # ragged
resp = OmniWidgetResponseModel(content=content)
# after
content = {"a": [1, 2], "b": [3, 4]}
resp = OmniWidgetResponseModel(content=content) Defensive patterns
Strategy: validation
Validate before calling
lengths = {len(v) for v in content.values() if isinstance(v, list)}
assert len(lengths) <= 1, f"ragged columns: {lengths}"
records = [dict(zip(content, row)) for row in zip(*content.values())]
resp = OmniWidgetResponseModel(content=records) Type guard
def is_wellformed_dict_of_lists(d) -> bool:
return isinstance(d, dict) and bool(d) and all(
isinstance(v, list) for v in d.values()
) and len({len(v) for v in d.values()}) == 1 Try / catch
try:
resp = OmniWidgetResponseModel(content=table_dict)
except ValueError as e:
if "dictionary of lists" in str(e):
raise ValueError(f"ragged table: { {k: len(v) for k, v in table_dict.items()} }") from e
raise Prevention
- Build dict-of-lists from a single loop so lengths stay aligned
- Assert equal list lengths at construction time
- Prefer passing a DataFrame or list of records directly
When it happens
Trigger: Constructing OmniWidgetResponseModel(content={'col_a': [...], 'col_b': [...]}) where list lengths differ (ValueError in pd.DataFrame construction), or the lists contain objects pandas/json cannot encode.
Common situations: Assembling a dict-of-lists from heterogeneous loops where one list ends up shorter or longer; embedding Timestamps, Decimals, or model objects inside the lists; an empty dict {} with other code paths mutating values.
Related errors
- Failed to convert DataFrame to JSON
- At least one extension type must be selected.
- Incorrect email or password
- Charting is not installed. Please install `openbb-charting`.
- Invalid command : route={route}
AI-assisted analysis of OpenBB-finance/OpenBB@3e071fcc2c (2026-08-14).
Data as JSON: /api/errors/a842af14087829f8.
Report an issue: GitHub.