{"record":{"id":"904e27052f74d388","repo":"zylon-ai/private-gpt","slug":"sandbox-not-started","errorCode":null,"errorMessage":"Sandbox not started","messagePattern":"Sandbox not started","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"private_gpt/components/tabular/pandasai_sandbox.py","lineNumber":480,"sourceCode":"        response_type = result.get(\"type\", \"string\")\n        response_value = result.get(\"value\")\n\n        if response_type == \"dataframe\" and isinstance(response_value, dict):\n            response_value = pd.DataFrame(\n                data=response_value[\"data\"],\n                index=response_value[\"index\"],\n                columns=response_value[\"columns\"],\n            )\n\n        return {\"type\": response_type, \"value\": response_value}\n\n    # ------------------------------------------------------------------\n    # File operations — every generated snippet is self-contained\n    # ------------------------------------------------------------------\n\n    def transfer_file(self, csv_data: pd.DataFrame, filename: str = \"file.csv\") -> None:\n        if not self._client:\n            raise RuntimeError(\"Sandbox not started\")\n\n        temp_dir = f\"/tmp/{self._user_id}\"\n        filepath = f\"{temp_dir}/{filename}\"\n        csv_content = csv_data.to_csv(index=False)\n\n        transfer_code = textwrap.dedent(\n            f\"\"\"\n            import os\n            os.makedirs({temp_dir!r}, exist_ok=True)\n            _csv_content = {csv_content!r}\n            with open({filepath!r}, 'w') as _f:\n                _f.write(_csv_content)\n            print(\"File transferred: {filepath}\")\n        \"\"\"\n        ).strip()\n\n        try:\n            result = self._run(","sourceCodeStart":462,"sourceCodeEnd":498,"githubUrl":"https://github.com/zylon-ai/private-gpt/blob/4a030776a31a901ad80b1bf4d7faa2c1a367efbb/private_gpt/components/tabular/pandasai_sandbox.py#L462-L498","documentation":"Guard in transfer_file(): pushing CSV data into the sandbox requires an active client (self._client); None means the sandbox was never started or was stopped. transfer_file writes the dataframe as a CSV inside the remote sandbox's per-user temp dir via run_code, so it is only valid between start() and stop().","triggerScenarios":"Calling transfer_file() before start(); after stop() nulled _client; after a failed start() left the adapter unusable; wrong object passed as sandbox in calling code.","commonSituations":"Custom integrations that upload context data before establishing the sandbox session; reuse of a cached adapter across requests after one request stopped it.","solutions":["Call start() (and confirm success) before transfer_file(); group all transfers inside the started session.","Create a fresh adapter per session/request rather than reusing stopped instances.","Add a lifecycle assertion/helper so all file ops go through one started-sandbox context."],"exampleFix":"# before\nsandbox.transfer_file(df, \"ctx.csv\")  # RuntimeError: Sandbox not started\n\n# after\nsandbox.start()\ntry:\n    sandbox.transfer_file(df, \"ctx.csv\")\nfinally:\n    sandbox.stop()","handlingStrategy":"validation","validationCode":"def transfer_is_safe(sandbox) -> bool:\n    return sandbox._client is not None  # i.e. started","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Perform all transfers inside one started session","Use a start/stop context manager around the whole analysis","Never call transfer_file after the chat call's finally stop()"],"tags":["sandbox","lifecycle","file-transfer","ordering"],"backgroundTag":null,"analyzedSha":"4a030776a31a901ad80b1bf4d7faa2c1a367efbb","analyzedAt":"2026-08-15T03:51:26.951Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}