zylon-ai/private-gpt · error · RuntimeError
Sandbox not started. Call start() first.
Error message
Sandbox not started. Call start() first.
What it means
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().
Source
Thrown at private_gpt/components/tabular/pandasai_sandbox.py:273
"""
).strip()
try:
result = self._run(
self._client.run_code(setup_code, SandboxCodeOptions(language="python"))
)
if not result.success:
logger.warning("Environment setup warning: %s", result.error)
except Exception as e:
logger.warning("Error during environment setup: %s", e)
# ------------------------------------------------------------------
# Code execution
# ------------------------------------------------------------------
def _exec_code(self, code: str, environment: dict[str, Any]) -> dict[str, Any]:
if not self._client:
raise RuntimeError("Sandbox not started. Call start() first.")
try:
sql_queries = self._extract_sql_queries_from_code(code)
datasets_code, exceptions = self._process_sql_queries(
sql_queries, environment
)
if exceptions:
raise ValueError(
f"Failed to execute some SQL queries: "
f"{', '.join(str(e) for e in exceptions)}"
)
processed_code = self._prepare_code_for_execution(code)
full_code = "\n\n".join(
part for part in (self._PREAMBLE, datasets_code, processed_code) if part
)
execution_result = self._run(View on GitHub (pinned to 4a030776a3)
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.
Example fix
# before
sandbox = PandasAISandboxAdapter(client=client, ...)
sandbox._exec_code(code, env) # RuntimeError
# after
from contextlib import contextmanager
@contextmanager
def started(sandbox):
sandbox.start()
try:
yield sandbox
finally:
sandbox.stop()
with started(sandbox):
sandbox._exec_code(code, env) Defensive patterns
Strategy: validation
Validate before calling
def is_started(sandbox) -> bool:
return sandbox._started and sandbox._client is not None
# guard every execution path:
# if not is_started(sandbox): sandbox.start() Prevention
- Wrap sandbox use in a start/stop context manager
- Never share an adapter across concurrent requests without locking
- Discard adapters whose start() failed
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Sandbox not started
- Sandbox client not configured
- Failed to start sandbox: {e}
- Client not initialized
- Path '{canonical_path}' does not match any session mount.
AI-assisted analysis of zylon-ai/private-gpt@4a030776a3 (2026-08-15).
Data as JSON: /api/errors/850427b4f79c6df1.
Report an issue: GitHub.