{"record":{"id":"ad596e26608b8399","repo":"langchain-ai/deepagents","slug":"notimplementederror-raised-by-abstract-execute","errorCode":null,"errorMessage":"NotImplementedError raised by abstract `execute` (backend does not implement `execute`)","messagePattern":"NotImplementedError raised by abstract `execute` \\(backend does not implement `execute`\\)","errorType":"exception","errorClass":"NotImplementedError","httpStatus":null,"severity":"error","filePath":"libs/deepagents/deepagents/backends/protocol.py","lineNumber":910,"sourceCode":"    ) -> ExecuteResponse:\n        \"\"\"Execute a shell command in the sandbox environment.\n\n        Simplified interface optimized for LLM consumption.\n\n        Args:\n            command: Full shell command string to execute.\n            timeout: Maximum time in seconds to wait for the command to complete.\n\n                If None, uses the backend's default timeout.\n\n                Callers should provide non-negative integer values for portable\n                behavior across backends. A value of 0 may disable timeouts on\n                backends that support no-timeout execution.\n\n        Returns:\n            `ExecuteResponse` with combined output, exit code, and truncation flag.\n        \"\"\"\n        raise NotImplementedError\n\n    async def aexecute(\n        self,\n        command: str,\n        *,\n        # ASYNC109 - timeout is a semantic parameter forwarded to the sync\n        # implementation, not an asyncio.timeout() contract.\n        timeout: int | None = None,  # noqa: ASYNC109\n    ) -> ExecuteResponse:\n        \"\"\"Async version of execute.\"\"\"\n        # The middleware layer validates timeout support before calling, so\n        # this guard only protects direct callers bypassing the middleware.\n        if timeout is not None and execute_accepts_timeout(type(self)):\n            return await asyncio.to_thread(self.execute, command, timeout=timeout)\n        return await asyncio.to_thread(self.execute, command)\n\n\n@lru_cache(maxsize=256)","sourceCodeStart":892,"sourceCodeEnd":928,"githubUrl":"https://github.com/langchain-ai/deepagents/blob/a1af029e6e73cb17c36bff823d227747b28e91e1/libs/deepagents/deepagents/backends/protocol.py#L892-L928","documentation":"`SandboxBackendProtocol.execute` is the core shell-execution method of a sandbox backend; the base-class stub raises `NotImplementedError` because every concrete sandbox must implement it. Calling `execute`/`aexecute` (directly or via setup helpers like `_run_sandbox_setup`) on a subclass that didn't override it raises this error. The async wrapper only forwards `timeout` when signature introspection (`execute_accepts_timeout`) shows support, so older backend packages also fail here in related ways.","triggerScenarios":"Calling `backend.execute('ls')` on a sandbox backend subclass missing an override; running sandbox setup/tests (`_run_sandbox_setup`, setup_test_dir) against an incomplete backend; instantiating the protocol class itself instead of a concrete backend.","commonSituations":"Custom sandbox backends that implemented file ops but not execution; passing the abstract protocol where a concrete backend is expected; mixed deepagents/backend package versions where the backend predates the `timeout` kwarg contract.","solutions":["Implement `execute(self, command, *, timeout=None) -> ExecuteResponse` in your sandbox backend class (and have `aexecute`/inherited async path delegate to it)","Use a concrete sandbox backend (e.g. LocalShellBackend or a partner sandbox package) instead of the protocol/base class directly","Align package versions so the backend satisfies the current `SandboxBackendProtocol` contract including the `timeout` kwarg","Inspect with `execute_accepts_timeout(type(backend))` before passing `timeout=` to older backends"],"exampleFix":"// before\nclass MySandbox(SandboxBackendProtocol):\n    @property\n    def id(self): return 'sb-1'\n\n// after\nclass MySandbox(SandboxBackendProtocol):\n    @property\n    def id(self): return 'sb-1'\n\n    def execute(self, command: str, *, timeout: int | None = None) -> ExecuteResponse:\n        proc = subprocess.run(command, shell=True, capture_output=True, timeout=timeout)\n        return ExecuteResponse(output=proc.stdout + proc.stderr, exit_code=proc.returncode)","handlingStrategy":"try-catch","validationCode":"from inspect import signature\n\ndef is_executable(backend) -> bool:\n    fn = getattr(type(backend), 'execute', None)\n    if fn is SandboxBackendProtocol.execute:\n        return False\n    try:\n        return 'command' in signature(fn).parameters\n    except (TypeError, ValueError):\n        return False","typeGuard":"def accepts_timeout(backend) -> bool:\n    return 'timeout' in signature(type(backend).execute).parameters","tryCatchPattern":"try:\n    resp = backend.execute(cmd, timeout=30)\nexcept NotImplementedError as e:\n    raise RuntimeError('backend does not support shell execution') from e","preventionTips":["Never instantiate SandboxBackendProtocol/BaseSandbox directly; use a concrete backend","Implement execute with the exact signature `(self, command: str, *, timeout: int | None = None)` so async delegation and timeout introspection work","Pin compatible deepagents/backend package versions and run protocol conformance tests in CI"],"tags":["python","not-implemented","sandbox","shell-execution"],"backgroundTag":"abstract-method-not-implemented","analyzedSha":"a1af029e6e73cb17c36bff823d227747b28e91e1","analyzedAt":"2026-08-29T11:43:24.718Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}