{"record":{"id":"db100890ad0fd9c7","repo":"zylon-ai/private-gpt","slug":"output-is-not-a-chart","errorCode":null,"errorMessage":"Output is not a chart","messagePattern":"Output is not a chart","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"warning","filePath":"private_gpt/components/tabular/pandasai_service.py","lineNumber":152,"sourceCode":"\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\n        for type_name, check_func in type_checks:\n            if check_func():\n                return type_name\n\n        return None\n","sourceCodeStart":134,"sourceCodeEnd":170,"githubUrl":"https://github.com/zylon-ai/private-gpt/blob/4a030776a31a901ad80b1bf4d7faa2c1a367efbb/private_gpt/components/tabular/pandasai_service.py#L134-L170","documentation":"PandasAIOutput.get_chart() narrowing accessor: valid only when isinstance(self.response, ChartResponse); it then extracts the embedded Image. Raises ValueError when the run did not produce a chart — i.e. the response wraps a DataFrame, string, or number instead.","triggerScenarios":"Calling get_chart() on an output whose value is a DataFrame/string/number; the generated code never created a plot; chart export path inside the sandbox failed so the response fell back to another type.","commonSituations":"UI code that unconditionally attaches a chart image for every tabular answer; prompt asked for a chart but the model produced a table instead.","solutions":["Check output.is_chart() before get_chart().","Use str(output) which returns a friendly message for charts and other types.","If a chart is mandatory, regenerate with a stricter prompt requiring a plot."],"exampleFix":"# before\nimg = output.get_chart()  # ValueError\n\n# after\nif output.is_chart():\n    img = output.get_chart()\nelse:\n    img = None","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"def as_chart_image(output):\n    return output.get_chart() if output.is_chart() else None","tryCatchPattern":null,"preventionTips":["Gate get_chart() behind is_chart()","Handle non-chart results with str(output) fallback","Strengthen the prompt when a chart is mandatory"],"tags":["pandas","type-narrowing","charts","accessor"],"backgroundTag":null,"analyzedSha":"4a030776a31a901ad80b1bf4d7faa2c1a367efbb","analyzedAt":"2026-08-15T03:51:26.951Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}