{"record":{"id":"850427b4f79c6df1","repo":"zylon-ai/private-gpt","slug":"sandbox-not-started-call-start-first","errorCode":null,"errorMessage":"Sandbox not started. Call start() first.","messagePattern":"Sandbox not started\\. Call start\\(\\) first\\.","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"private_gpt/components/tabular/pandasai_sandbox.py","lineNumber":273,"sourceCode":"        \"\"\"\n        ).strip()\n\n        try:\n            result = self._run(\n                self._client.run_code(setup_code, SandboxCodeOptions(language=\"python\"))\n            )\n            if not result.success:\n                logger.warning(\"Environment setup warning: %s\", result.error)\n        except Exception as e:\n            logger.warning(\"Error during environment setup: %s\", e)\n\n    # ------------------------------------------------------------------\n    # Code execution\n    # ------------------------------------------------------------------\n\n    def _exec_code(self, code: str, environment: dict[str, Any]) -> dict[str, Any]:\n        if not self._client:\n            raise RuntimeError(\"Sandbox not started. Call start() first.\")\n\n        try:\n            sql_queries = self._extract_sql_queries_from_code(code)\n            datasets_code, exceptions = self._process_sql_queries(\n                sql_queries, environment\n            )\n            if exceptions:\n                raise ValueError(\n                    f\"Failed to execute some SQL queries: \"\n                    f\"{', '.join(str(e) for e in exceptions)}\"\n                )\n\n            processed_code = self._prepare_code_for_execution(code)\n            full_code = \"\\n\\n\".join(\n                part for part in (self._PREAMBLE, datasets_code, processed_code) if part\n            )\n\n            execution_result = self._run(","sourceCodeStart":255,"sourceCodeEnd":291,"githubUrl":"https://github.com/zylon-ai/private-gpt/blob/4a030776a31a901ad80b1bf4d7faa2c1a367efbb/private_gpt/components/tabular/pandasai_sandbox.py#L255-L291","documentation":"Guard inside _exec_code(): generated Python is executed remotely through self._client, and a None client means the sandbox session was never started (or was stopped). This is a lifecycle-order error — the adapter is stateful and _exec_code is only valid between start() and stop().","triggerScenarios":"Calling chat()/execution flows with sandbox=None vs a not-yet-started adapter; executing code after stop() ran (stop() sets _client=None at line 185); a start() failure earlier in the request leaving the adapter in a dead state.","commonSituations":"Missing sandbox.start() in a new integration path; exception in a prior request leaving the adapter stopped but still cached; concurrency where one request stops the shared adapter while another is mid-flight.","solutions":["Ensure start() is called (and succeeded) before any code execution; PandasAIService._chat_with_sandbox already does this — reuse that path.","Do not share one adapter across concurrent requests without a lock; stop() from one request nulls _client for all.","After any start() failure, discard the adapter instance instead of reusing it.","If hitting this in tests, wrap execution with a context manager that starts/stops the sandbox."],"exampleFix":"# before\nsandbox = PandasAISandboxAdapter(client=client, ...)\nsandbox._exec_code(code, env)  # RuntimeError\n\n# after\nfrom contextlib import contextmanager\n\n@contextmanager\ndef started(sandbox):\n    sandbox.start()\n    try:\n        yield sandbox\n    finally:\n        sandbox.stop()\n\nwith started(sandbox):\n    sandbox._exec_code(code, env)","handlingStrategy":"validation","validationCode":"def is_started(sandbox) -> bool:\n    return sandbox._started and sandbox._client is not None\n\n# guard every execution path:\n# if not is_started(sandbox): sandbox.start()","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Wrap sandbox use in a start/stop context manager","Never share an adapter across concurrent requests without locking","Discard adapters whose start() failed"],"tags":["sandbox","lifecycle","ordering","state-management"],"backgroundTag":null,"analyzedSha":"4a030776a31a901ad80b1bf4d7faa2c1a367efbb","analyzedAt":"2026-08-15T03:51:26.951Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}