{"record":{"id":"7b8dd433de41f232","repo":"BerriAI/litellm","slug":"adelete-sandbox-must-be-implemented-by-provider","errorCode":null,"errorMessage":"adelete_sandbox must be implemented by provider","messagePattern":"adelete_sandbox must be implemented by provider","errorType":"exception","errorClass":"NotImplementedError","httpStatus":null,"severity":"error","filePath":"litellm/llms/base_llm/sandbox/transformation.py","lineNumber":80,"sourceCode":"\n    async def arun_code(\n        self,\n        *,\n        container: ContainerHandle | str,\n        code: str,\n        api_key: str | None = None,\n        **kwargs,\n    ) -> CodeExecutionResult:\n        raise NotImplementedError(\"arun_code must be implemented by provider\")\n\n    async def adelete_sandbox(\n        self,\n        *,\n        container: ContainerHandle | str,\n        api_key: str | None = None,\n        **kwargs,\n    ) -> bool:\n        raise NotImplementedError(\"adelete_sandbox must be implemented by provider\")\n\n    async def _read_capped_lines(self, response: httpx.Response) -> list[str]:\n        lines: Final[list[str]] = []\n        total = 0\n        async for line in response.aiter_lines():\n            total += len(line.encode(\"utf-8\"))\n            if total > SANDBOX_MAX_OUTPUT_BYTES:\n                raise ValueError(\n                    f\"Sandbox output exceeded {SANDBOX_MAX_OUTPUT_BYTES} bytes; aborting to avoid unbounded memory use.\"\n                )\n            lines.append(line)\n        return lines\n","sourceCodeStart":62,"sourceCodeEnd":93,"githubUrl":"https://github.com/BerriAI/litellm/blob/6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d/litellm/llms/base_llm/sandbox/transformation.py#L62-L93","documentation":"BaseSandboxConfig.adelete_sandbox() is the abstract teardown hook for destroying a sandbox container; it must return bool. The base class raises NotImplementedError to force provider implementations. Encountering it means the delete path ran against the base or an incomplete custom config, so the container was NOT deleted (leaked resources).","triggerScenarios":"Calling the sandbox delete/cleanup API when the active provider config does not override adelete_sandbox — custom subclasses or a provider fallback to BaseSandboxConfig.","commonSituations":"Custom provider implementers who implemented create/run but not delete; cleanup code (finally blocks, GC hooks) hitting the stub and leaking billed containers.","solutions":["Implement `async def adelete_sandbox(self, *, container, api_key=None, **kwargs) -> bool` in your custom config.","Switch to a fully implemented provider (OpenSandbox/E2B) if you did not intend to write a custom one.","Until fixed, manually delete leaked containers via the provider's dashboard/API."],"exampleFix":"# before\nclass MySandbox(BaseSandboxConfig):\n    pass\nawait sandbox.adelete_sandbox(container=h)  # raises; container leaks\n\n# after\nclass MySandbox(BaseSandboxConfig):\n    async def adelete_sandbox(self, *, container, api_key=None, **kwargs) -> bool:\n        resp = await self._client.delete(f\"/containers/{container.id}\")\n        return resp.status_code in (200, 204)","handlingStrategy":"try-catch","validationCode":"from litellm.llms.base_llm.sandbox.transformation import BaseSandboxConfig\n\nassert type(cfg).adelete_sandbox is not BaseSandboxConfig.adelete_sandbox, \"adelete_sandbox not implemented\"","typeGuard":"from litellm.llms.base_llm.sandbox.transformation import BaseSandboxConfig\n\ndef supports_delete_sandbox(cfg: BaseSandboxConfig) -> bool:\n    return type(cfg).adelete_sandbox is not BaseSandboxConfig.adelete_sandbox","tryCatchPattern":"try:\n    ok = await cfg.adelete_sandbox(container=handle)\nfinally:\n    if not ok:\n        record_leaked_container(handle.id)  # ensure cleanup is trackable","preventionTips":["Wrap sandbox lifecycle in try/finally so delete failures don't lose the handle id.","Run periodic reconciliation against the provider API to catch leaked containers."],"tags":["sandbox","not-implemented","resource-cleanup","litellm"],"backgroundTag":null,"analyzedSha":"6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d","analyzedAt":"2026-08-15T07:12:03.035Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}