Summary
We are seeing intermittent failures in OpenSandbox when using the Python code-interpreter API:
session.interpreter.codes.run(
code,
language=SupportedLanguage.PYTHON,
)
The issue appears specific to the Python/Jupyter code-interpreter path. Shell execution through session.sandbox.commands.run(...) appears to be a different path and is not the main source of these
failures.
We have observed two related failure modes:
- codes.run() hangs for a long time while the Jupyter kernel is actually idle.
- codes.run() fails with RemoteProtocolError: peer closed connection without sending complete message body (incomplete chunked read).
Both cases happen with simple pandas/matplotlib/seaborn code, not long-running or resource-intensive computation.
———
Environment
- OpenSandbox image: custom image based on OpenSandbox code-interpreter environment
- Runtime: local Docker-based OpenSandbox
- Python in sandbox: 3.11
- Backend: Python async service calling OpenSandbox SDK
- Code execution path: CodeInterpreter.codes.run(...)
- Shell execution path: sandbox.commands.run(...)
———
Failure mode 1: codes.run() hangs while Jupyter kernel is idle
Observed behavior
A simple matplotlib/seaborn plotting cell appeared to run for more than 20 minutes. However, inspecting the sandbox showed:
- Docker container CPU was near 0%.
- No target output file was created.
- Jupyter kernel API reported:
- execution_state: "idle"
- last_activity was from the previous successful cell.
- The backend was still awaiting session.interpreter.codes.run(...).
This suggests that the code was not actually executing in the kernel. The SDK call was waiting on the code-interpreter/Jupyter communication path.
Example code that appeared stuck
fig, axes = plt.subplots(2, 2, figsize=(14, 10))
sns.boxplot(data=df, x='pickup_borough', y='fare', ax=axes[0, 0])
sns.boxplot(data=df, x='color', y='fare', ax=axes[0, 1])
passenger_counts = df['passengers'].value_counts().sort_index()
axes[1, 0].bar(passenger_counts.index, passenger_counts.values)
sns.boxplot(data=df[df['payment'].notna()], x='payment', y='fare', ax=axes[1, 1])
plt.tight_layout()
plt.savefig('/tmp/workspace/chart08_boxplots.png', dpi=150, bbox_inches='tight')
plt.close()
print("Chart 8 saved.")
Evidence
During the hang:
Jupyter kernel:
execution_state: idle
last_activity: previous successful execution timestamp
Docker stats showed low CPU usage and normal memory usage.
The target file did not exist in /tmp/workspace.
After our application-level timeout/recovery logic recreated the sandbox and resynced files, the same kind of plotting continued successfully.
———
Failure mode 2: incomplete chunked read / peer closed connection
Observed behavior
A simple first EDA cell failed with:
Execution error: Unexpected SDK error occurred: peer closed connection without sending complete message body (incomplete chunked read)
Backend logs showed:
httpcore.RemoteProtocolError: peer closed connection without sending complete message body (incomplete chunked read)
httpx.RemoteProtocolError: peer closed connection without sending complete message body (incomplete chunked read)
Connection lost for session user-2, cleaning up dead session...
Then sandbox cleanup also hit:
Conflict: removal of container ... is already in progress
The backend then recreated the sandbox, resynced the uploaded file, and subsequent code continued to run.
Example code
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import warnings
warnings.filterwarnings('ignore')
df = pd.read_csv('/tmp/workspace/healthexp.csv')
print("=" * 60)
print("DATASET OVERVIEW")
print("=" * 60)
print(f"\nShape: {df.shape}")
print(f"Rows: {df.shape[0]}, Columns: {df.shape[1]}")
print(f"\nColumn Names:\n{df.columns.tolist()}")
print(f"\nData Types:\n{df.dtypes}")
print("\nFirst 10 rows:")
df.head(10)
Error returned to caller
[KERNEL_RESTARTED] The sandbox Python kernel/container was recreated. In-memory variables from earlier steps are gone. Uploaded input files have been re-synced to /tmp/workspace; reload the dataset
before continuing.
[STDERR] Execution error: Unexpected SDK error occurred: peer closed connection without sending complete message body (incomplete chunked read)
Note: Sandbox session may have expired due to inactivity. Please retry your request.
———
Expected behavior
For CodeInterpreter.codes.run(...):
- If the kernel is idle and no execution is in progress, the SDK call should not hang indefinitely.
- If the HTTP streaming connection is closed prematurely, the SDK should surface a clear, typed exception.
- The SDK/runtime should avoid leaving the caller waiting while the kernel is idle.
- Cleanup should handle already-removing containers gracefully.
———
Questions
- Is CodeInterpreter.codes.run() expected to rely on a long-lived streaming HTTP response?
- Is there a recommended heartbeat or timeout strategy for detecting “kernel idle but SDK call still waiting”?
- Is there a supported way to query/interrupt/reset only the code-interpreter/Jupyter session without recreating the whole sandbox?
- Should the SDK catch httpx.RemoteProtocolError / httpcore.RemoteProtocolError and convert it into a documented OpenSandbox exception?
- Is sandbox.commands.run(...) recommended for long-running Python scripts instead of CodeInterpreter.codes.run(...)?
———
Workaround we are considering
For reliability, we are considering using:
write_file("analysis.py", code)
sandbox.commands.run("cd /tmp/workspace && python3 analysis.py")
instead of:
CodeInterpreter.codes.run(code, language=PYTHON)
for longer data analysis workflows.
This avoids the persistent Jupyter/kernel channel but loses Python variable persistence across calls.
Summary
We are seeing intermittent failures in OpenSandbox when using the Python code-interpreter API:
The issue appears specific to the Python/Jupyter code-interpreter path. Shell execution through session.sandbox.commands.run(...) appears to be a different path and is not the main source of these
failures.
We have observed two related failure modes:
Both cases happen with simple pandas/matplotlib/seaborn code, not long-running or resource-intensive computation.
———
Environment
———
Failure mode 1: codes.run() hangs while Jupyter kernel is idle
Observed behavior
A simple matplotlib/seaborn plotting cell appeared to run for more than 20 minutes. However, inspecting the sandbox showed:
This suggests that the code was not actually executing in the kernel. The SDK call was waiting on the code-interpreter/Jupyter communication path.
Example code that appeared stuck
Evidence
During the hang:
Jupyter kernel:
execution_state: idle
last_activity: previous successful execution timestamp
Docker stats showed low CPU usage and normal memory usage.
The target file did not exist in /tmp/workspace.
After our application-level timeout/recovery logic recreated the sandbox and resynced files, the same kind of plotting continued successfully.
———
Failure mode 2: incomplete chunked read / peer closed connection
Observed behavior
A simple first EDA cell failed with:
Execution error: Unexpected SDK error occurred: peer closed connection without sending complete message body (incomplete chunked read)
Backend logs showed:
httpcore.RemoteProtocolError: peer closed connection without sending complete message body (incomplete chunked read)
httpx.RemoteProtocolError: peer closed connection without sending complete message body (incomplete chunked read)
Connection lost for session user-2, cleaning up dead session...
Then sandbox cleanup also hit:
Conflict: removal of container ... is already in progress
The backend then recreated the sandbox, resynced the uploaded file, and subsequent code continued to run.
Example code
Error returned to caller
[KERNEL_RESTARTED] The sandbox Python kernel/container was recreated. In-memory variables from earlier steps are gone. Uploaded input files have been re-synced to /tmp/workspace; reload the dataset
before continuing.
[STDERR] Execution error: Unexpected SDK error occurred: peer closed connection without sending complete message body (incomplete chunked read)
Note: Sandbox session may have expired due to inactivity. Please retry your request.
———
Expected behavior
For CodeInterpreter.codes.run(...):
———
Questions
———
Workaround we are considering
For reliability, we are considering using:
write_file("analysis.py", code)
sandbox.commands.run("cd /tmp/workspace && python3 analysis.py")
instead of:
CodeInterpreter.codes.run(code, language=PYTHON)
for longer data analysis workflows.
This avoids the persistent Jupyter/kernel channel but loses Python variable persistence across calls.