{"record":{"id":"a785ea85363caa73","repo":"FoundationAgents/OpenManus","slug":"maximum-number-of-sandboxes-self-max-sandboxes","errorCode":null,"errorMessage":"Maximum number of sandboxes ({self.max_sandboxes}) reached","messagePattern":"Maximum number of sandboxes \\((.+?)\\) reached","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"app/sandbox/core/manager.py","lineNumber":133,"sourceCode":"        self,\n        config: Optional[SandboxSettings] = None,\n        volume_bindings: Optional[Dict[str, str]] = None,\n    ) -> str:\n        \"\"\"Creates a new sandbox instance.\n\n        Args:\n            config: Sandbox configuration.\n            volume_bindings: Volume mapping configuration.\n\n        Returns:\n            str: Sandbox ID.\n\n        Raises:\n            RuntimeError: If max sandbox count reached or creation fails.\n        \"\"\"\n        async with self._global_lock:\n            if len(self._sandboxes) >= self.max_sandboxes:\n                raise RuntimeError(\n                    f\"Maximum number of sandboxes ({self.max_sandboxes}) reached\"\n                )\n\n            config = config or SandboxSettings()\n            if not await self.ensure_image(config.image):\n                raise RuntimeError(f\"Failed to ensure Docker image: {config.image}\")\n\n            sandbox_id = str(uuid.uuid4())\n            try:\n                sandbox = DockerSandbox(config, volume_bindings)\n                await sandbox.create()\n\n                self._sandboxes[sandbox_id] = sandbox\n                self._last_used[sandbox_id] = asyncio.get_event_loop().time()\n                self._locks[sandbox_id] = asyncio.Lock()\n\n                logger.info(f\"Created sandbox {sandbox_id}\")\n                return sandbox_id","sourceCodeStart":115,"sourceCodeEnd":151,"githubUrl":"https://github.com/FoundationAgents/OpenManus/blob/52a13f2a57d8c7f6737eefb02ccf569594d44273/app/sandbox/core/manager.py#L115-L151","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"# before\nsid = await manager.create_sandbox(config)\nresult = await run_task(sid)  # sandbox leaked on exception\n\n# after\nsid = await manager.create_sandbox(config)\ntry:\n    result = await run_task(sid)\nfinally:\n    await manager.delete_sandbox(sid)","handlingStrategy":"validation","validationCode":"if manager.active_count() >= manager.max_sandboxes:\n    sid = await manager.get_idle_sandbox() or await manager.reap_idle_sandbox()\n    # reuse or free before creating\nsid = await manager.create_sandbox(config)","typeGuard":null,"tryCatchPattern":"try:\n    sid = await manager.create_sandbox(config)\nexcept RuntimeError as e:\n    if \"Maximum number of sandboxes\" in str(e):\n        await manager.delete_sandbox(oldest_active_id())\n        sid = await manager.create_sandbox(config)\n    else:\n        raise","preventionTips":["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"],"tags":["sandbox","docker","capacity","resource-leak","limits"],"backgroundTag":null,"analyzedSha":"52a13f2a57d8c7f6737eefb02ccf569594d44273","analyzedAt":"2026-08-15T02:33:49.993Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}