{"record":{"id":"4688604b5b485119","repo":"zylon-ai/private-gpt","slug":"output-is-not-a-pd-dataframe","errorCode":null,"errorMessage":"Output is not a pd.DataFrame","messagePattern":"Output is not a pd\\.DataFrame","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"warning","filePath":"private_gpt/components/tabular/pandasai_service.py","lineNumber":146,"sourceCode":"    def is_number(self) -> bool:\n        \"\"\"Check if the value is a number.\"\"\"\n        # Try to cast to int, float, or complex\n        return isinstance(self.value, int | float | complex) and not isinstance(\n            self.value, bool\n        )\n\n    def is_dataframe(self) -> bool:\n        \"\"\"Check if the value is a pandas DataFrame.\"\"\"\n        return isinstance(self.value, pd.DataFrame)\n\n    def is_chart(self) -> bool:\n        \"\"\"Check if the response is a chart.\"\"\"\n        return isinstance(self.response, ChartResponse)\n\n    def get_dataframe(self) -> pd.DataFrame:\n        \"\"\"Get the value as a DataFrame, or raise an error.\"\"\"\n        if not self.is_dataframe():\n            raise ValueError(\"Output is not a pd.DataFrame\")\n        return cast(pd.DataFrame, self.value)\n\n    def get_chart(self) -> Image:\n        \"\"\"Get the chart as an Image, or raise an error.\"\"\"\n        if not self.is_chart():\n            raise ValueError(\"Output is not a chart\")\n        img = cast(ChartResponse, self.response)._get_image()\n        return cast(Image, img)\n\n    def _determine_response_type(self) -> str | None:\n        \"\"\"Determine the response type for dispatching.\"\"\"\n        type_checks = [\n            (\"dataframe\", self.is_dataframe),\n            (\"chart\", self.is_chart),\n            (\"string\", self.is_string),\n            (\"number\", self.is_number),\n        ]\n","sourceCodeStart":128,"sourceCodeEnd":164,"githubUrl":"https://github.com/zylon-ai/private-gpt/blob/4a030776a31a901ad80b1bf4d7faa2c1a367efbb/private_gpt/components/tabular/pandasai_service.py#L128-L164","documentation":"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).","triggerScenarios":"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'.","commonSituations":"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.","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."],"exampleFix":"# before\ndf = output.get_dataframe()  # ValueError when result is a chart\n\n# after\nif output.is_dataframe():\n    df = output.get_dataframe()\nelse:\n    df = None  # or handle chart/string/number branches","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"def as_dataframe(output):\n    return output.get_dataframe() if output.is_dataframe() else None","tryCatchPattern":null,"preventionTips":["Always branch with is_dataframe() first","Prefer str(output) for display paths","Instruct the model explicitly when a tabular result is required"],"tags":["pandas","type-narrowing","accessor","llm-output"],"backgroundTag":null,"analyzedSha":"4a030776a31a901ad80b1bf4d7faa2c1a367efbb","analyzedAt":"2026-08-15T03:51:26.951Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}