zylon-ai/private-gpt · warning · ValueError
Output is not a pd.DataFrame
Error message
Output is not a pd.DataFrame
What it means
PandasAIOutput.get_dataframe() is a narrowing accessor: it returns self.value as a pd.DataFrame only when isinstance(self.value, pd.DataFrame) holds; otherwise ValueError. The output value's type depends on what the generated code last-expression/last-produced value was, so this fires when the analysis returned something other than a frame (a string, number, or chart).
Source
Thrown at private_gpt/components/tabular/pandasai_service.py:146
def is_number(self) -> bool:
"""Check if the value is a number."""
# Try to cast to int, float, or complex
return isinstance(self.value, int | float | complex) and not isinstance(
self.value, bool
)
def is_dataframe(self) -> bool:
"""Check if the value is a pandas DataFrame."""
return isinstance(self.value, pd.DataFrame)
def is_chart(self) -> bool:
"""Check if the response is a chart."""
return isinstance(self.response, ChartResponse)
def get_dataframe(self) -> pd.DataFrame:
"""Get the value as a DataFrame, or raise an error."""
if not self.is_dataframe():
raise ValueError("Output is not a pd.DataFrame")
return cast(pd.DataFrame, self.value)
def get_chart(self) -> Image:
"""Get the chart as an Image, or raise an error."""
if not self.is_chart():
raise ValueError("Output is not a chart")
img = cast(ChartResponse, self.response)._get_image()
return cast(Image, img)
def _determine_response_type(self) -> str | None:
"""Determine the response type for dispatching."""
type_checks = [
("dataframe", self.is_dataframe),
("chart", self.is_chart),
("string", self.is_string),
("number", self.is_number),
]
View on GitHub (pinned to 4a030776a3)
Solutions
- Branch on output.is_dataframe() (or _determine_response_type) before calling get_dataframe().
- Use str(output) or the handlers dict which handles all types gracefully.
- If a frame is required, re-prompt the analysis with an explicit instruction to return a DataFrame.
Example fix
# before
df = output.get_dataframe() # ValueError when result is a chart
# after
if output.is_dataframe():
df = output.get_dataframe()
else:
df = None # or handle chart/string/number branches Defensive patterns
Strategy: type-guard
Type guard
def as_dataframe(output):
return output.get_dataframe() if output.is_dataframe() else None Prevention
- Always branch with is_dataframe() first
- Prefer str(output) for display paths
- Instruct the model explicitly when a tabular result is required
When it happens
Trigger: Calling get_dataframe() after a chat run whose result is a chart (ChartResponse), a string, or a number; the generated code's final value is a print-out or scalar rather than a DataFrame; response-type dispatch said 'chart' or 'string'.
Common situations: Caller assumes tabular output for every query, but the user's prompt asked for a plot or a single number; mixed workloads where the same handler must branch on result type.
Related errors
- Output is not a chart
- Output is not a string, number, pd.DataFrame, or chart
- Failed to parse JSON: {e!s}
- Invalid CALL statement format
- Failed to execute some SQL queries: {', '.join(str(e) for e
AI-assisted analysis of zylon-ai/private-gpt@4a030776a3 (2026-08-15).
Data as JSON: /api/errors/4688604b5b485119.
Report an issue: GitHub.