zylon-ai/private-gpt · error · RuntimeError

Sandbox not started

Error message

Sandbox not started

What it means

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().

Source

Thrown at private_gpt/components/tabular/pandasai_sandbox.py:480

        response_type = result.get("type", "string")
        response_value = result.get("value")

        if response_type == "dataframe" and isinstance(response_value, dict):
            response_value = pd.DataFrame(
                data=response_value["data"],
                index=response_value["index"],
                columns=response_value["columns"],
            )

        return {"type": response_type, "value": response_value}

    # ------------------------------------------------------------------
    # File operations — every generated snippet is self-contained
    # ------------------------------------------------------------------

    def transfer_file(self, csv_data: pd.DataFrame, filename: str = "file.csv") -> None:
        if not self._client:
            raise RuntimeError("Sandbox not started")

        temp_dir = f"/tmp/{self._user_id}"
        filepath = f"{temp_dir}/{filename}"
        csv_content = csv_data.to_csv(index=False)

        transfer_code = textwrap.dedent(
            f"""
            import os
            os.makedirs({temp_dir!r}, exist_ok=True)
            _csv_content = {csv_content!r}
            with open({filepath!r}, 'w') as _f:
                _f.write(_csv_content)
            print("File transferred: {filepath}")
        """
        ).strip()

        try:
            result = self._run(

View on GitHub (pinned to 4a030776a3)

Solutions

  1. Call start() (and confirm success) before transfer_file(); group all transfers inside the started session.
  2. Create a fresh adapter per session/request rather than reusing stopped instances.
  3. Add a lifecycle assertion/helper so all file ops go through one started-sandbox context.

Example fix

# before
sandbox.transfer_file(df, "ctx.csv")  # RuntimeError: Sandbox not started

# after
sandbox.start()
try:
    sandbox.transfer_file(df, "ctx.csv")
finally:
    sandbox.stop()
Defensive patterns

Strategy: validation

Validate before calling

def transfer_is_safe(sandbox) -> bool:
    return sandbox._client is not None  # i.e. started

Prevention

When it happens

Trigger: 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.

Common situations: Custom integrations that upload context data before establishing the sandbox session; reuse of a cached adapter across requests after one request stopped it.

Related errors


AI-assisted analysis of zylon-ai/private-gpt@4a030776a3 (2026-08-15). Data as JSON: /api/errors/904e27052f74d388. Report an issue: GitHub.