FoundationAgents/OpenManus · error · RuntimeError
Maximum number of sandboxes
Error message
Maximum number of sandboxes ({self.max_sandboxes}) reached What it means
Raised by SandboxManager.create_sandbox (app/sandbox/core/manager.py:133) while holding _global_lock when len(self._sandboxes) >= self.max_sandboxes. It is a hard capacity cap: the manager refuses to allocate a new Docker sandbox until an existing one is deleted. Because the check happens under the global lock, concurrent creators serialize and the first one past the cap fails.
Solutions
- Delete sandboxes you no longer need: await manager.delete_sandbox(sandbox_id) in a finally block.
- Reuse sandboxes from the pool (get an existing idle one) instead of creating a new one per task.
- Increase max_sandboxes in the manager configuration if host resources allow.
- Add a periodic reaper that deletes sandboxes idle since _last_used beyond a threshold.
Example fix
# before
sid = await manager.create_sandbox(config)
result = await run_task(sid) # sandbox leaked on exception
# after
sid = await manager.create_sandbox(config)
try:
result = await run_task(sid)
finally:
await manager.delete_sandbox(sid) Defensive patterns
Strategy: validation
Validate before calling
if manager.active_count() >= manager.max_sandboxes:
sid = await manager.get_idle_sandbox() or await manager.reap_idle_sandbox()
# reuse or free before creating
sid = await manager.create_sandbox(config) Try / catch
try:
sid = await manager.create_sandbox(config)
except RuntimeError as e:
if "Maximum number of sandboxes" in str(e):
await manager.delete_sandbox(oldest_active_id())
sid = await manager.create_sandbox(config)
else:
raise Prevention
- Always pair create_sandbox with delete_sandbox in try/finally
- Run a periodic reaper keyed on manager._last_used
- Keep max_sandboxes below host memory / disk capacity
- Pool and reuse sandboxes per task type instead of one per request
When it happens
Trigger: Creating sandboxes in a loop (one per task/request) without calling delete_sandbox; leaking sandboxes after exceptions so _sandboxes only grows; running concurrent agent sessions whose combined sandbox count hits max_sandboxes.
Common situations: No reaping of idle sandboxes in a long-lived service; a request handler that allocates a sandbox per request but only frees it on the happy path; miscounting because delete_sandbox was never awaited after an error.
Related errors
- Empty tar archive
- Failed to create sandbox
- Failed to create sandbox
- Command ' ' timed out after seconds in sandbox
- Command execution timed out after
AI-assisted analysis of FoundationAgents/OpenManus@52a13f2a57 (2026-08-15).
Data as JSON: /api/errors/a785ea85363caa73.
Report an issue: GitHub.
Appendix: source
Thrown at app/sandbox/core/manager.py:133
self,
config: Optional[SandboxSettings] = None,
volume_bindings: Optional[Dict[str, str]] = None,
) -> str:
"""Creates a new sandbox instance.
Args:
config: Sandbox configuration.
volume_bindings: Volume mapping configuration.
Returns:
str: Sandbox ID.
Raises:
RuntimeError: If max sandbox count reached or creation fails.
"""
async with self._global_lock:
if len(self._sandboxes) >= self.max_sandboxes:
raise RuntimeError(
f"Maximum number of sandboxes ({self.max_sandboxes}) reached"
)
config = config or SandboxSettings()
if not await self.ensure_image(config.image):
raise RuntimeError(f"Failed to ensure Docker image: {config.image}")
sandbox_id = str(uuid.uuid4())
try:
sandbox = DockerSandbox(config, volume_bindings)
await sandbox.create()
self._sandboxes[sandbox_id] = sandbox
self._last_used[sandbox_id] = asyncio.get_event_loop().time()
self._locks[sandbox_id] = asyncio.Lock()
logger.info(f"Created sandbox {sandbox_id}")
return sandbox_idView on GitHub (pinned to 52a13f2a57)