{"record":{"id":"51125e73f15a9faa","repo":"langchain-ai/deepagents","slug":"notimplementederror-raised-by-abstract-delete-b","errorCode":null,"errorMessage":"NotImplementedError raised by abstract `delete` (backend does not implement `delete`)","messagePattern":"NotImplementedError raised by abstract `delete` \\(backend does not implement `delete`\\)","errorType":"exception","errorClass":"NotImplementedError","httpStatus":null,"severity":"error","filePath":"libs/deepagents/deepagents/backends/protocol.py","lineNumber":748,"sourceCode":"\n        Deletion is recursive: it removes `file_path` plus everything nested\n        under it. On hierarchical backends (e.g.\n        [`FilesystemBackend`][deepagents.backends.filesystem.FilesystemBackend])\n        that means a directory and its contents; on key-value backends it means\n        the exact key plus every key sharing the `file_path` + \"/\" prefix.\n\n        Args:\n            file_path: Absolute path to delete (a file, or a directory/prefix to\n                remove recursively). Must start with '/'.\n\n        Returns:\n            `DeleteResult` with the deleted path on success, or an error if\n                nothing exists at or under the path or removal fails.\n\n        Raises:\n            NotImplementedError: If the backend does not implement `delete`.\n        \"\"\"\n        raise NotImplementedError\n\n    async def adelete(self, file_path: str) -> DeleteResult:\n        \"\"\"Async version of `delete`.\"\"\"\n        return await asyncio.to_thread(self.delete, file_path)\n\n    def upload_files(self, files: list[tuple[str, bytes]]) -> list[FileUploadResponse]:\n        \"\"\"Upload multiple files to the sandbox.\n\n        This API is designed to allow developers to use it either directly or by\n        exposing it to LLMs via custom tools.\n\n        Args:\n            files: List of (path, content) tuples to upload.\n\n        Returns:\n            List of `FileUploadResponse` objects, one per input file.\n\n                Response order matches input order (`response[i] for files[i]`).","sourceCodeStart":730,"sourceCodeEnd":766,"githubUrl":"https://github.com/langchain-ai/deepagents/blob/a1af029e6e73cb17c36bff823d227747b28e91e1/libs/deepagents/deepagents/backends/protocol.py#L730-L766","documentation":"`BackendProtocol.delete` is an optional capability: backends that don't override it inherit this base-class stub, which raises `NotImplementedError` when called. Deletion (recursive removal of a path or prefix) is not supported by every backend, so the protocol deliberately defaults to raising rather than silently failing. The docstring tells callers to guard with `supports_delete` or catch `NotImplementedError`.","triggerScenarios":"Calling `backend.delete(path)` (or `await backend.adelete(path)`) on a backend class that does not override `delete`, e.g. a minimal custom `BackendProtocol` subclass or a key-value backend without delete support. Also hit indirectly by tools/middleware that route delete operations to a backend lacking the capability.","commonSituations":"Writing a custom backend and forgetting to implement `delete`; switching a deep agent from a filesystem backend to a state/store backend that doesn't support deletion; generic code paths that assume all backends can delete.","solutions":["Check support first with `supports_delete(backend)` (or `type(backend).delete is not BackendProtocol.delete`) before calling","Wrap the call in try/except NotImplementedError and return a 'delete unsupported' result for mixed-backend code","Switch to a backend that implements delete, e.g. FilesystemBackend","Implement `delete` in your custom backend subclass"],"exampleFix":"// before\nresult = backend.delete('/tmp/scratch')\n\n// after\nfrom deepagents.backends.protocol import supports_delete\nif supports_delete(backend):\n    result = backend.delete('/tmp/scratch')\nelse:\n    result = DeleteResult(error='delete not supported by this backend')","handlingStrategy":"validation","validationCode":"from deepagents.backends.protocol import BackendProtocol\n\ndef supports_delete(backend: BackendProtocol) -> bool:\n    return type(backend).delete is not BackendProtocol.delete\n\nif not supports_delete(backend):\n    raise RuntimeError(f'{type(backend).__name__} does not support delete')","typeGuard":"def is_deletable(backend) -> bool:\n    return type(backend).delete is not BackendProtocol.delete","tryCatchPattern":"from deepagents.backends.protocol import DeleteResult\ntry:\n    result = backend.delete(path)\nexcept NotImplementedError:\n    result = DeleteResult(files=[], error='delete not supported by this backend')","preventionTips":["Always guard optional backend capabilities with supports_* style checks before calling","When writing a custom backend, decide explicitly which optional methods (delete, upload_files, download_files) you implement and document the rest as unsupported","Add a capability smoke test per backend in CI"],"tags":["python","not-implemented","backend-protocol","optional-capability"],"backgroundTag":"abstract-method-not-implemented","analyzedSha":"a1af029e6e73cb17c36bff823d227747b28e91e1","analyzedAt":"2026-08-29T11:43:24.718Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}