{"record":{"id":"68d3fad0597b7edd","repo":"langchain-ai/deepagents","slug":"notimplementederror-raised-by-abstract-read-bac","errorCode":null,"errorMessage":"NotImplementedError raised by abstract `read` (backend does not implement `read`)","messagePattern":"NotImplementedError raised by abstract `read` \\(backend does not implement `read`\\)","errorType":"exception","errorClass":"NotImplementedError","httpStatus":null,"severity":"error","filePath":"libs/deepagents/deepagents/backends/protocol.py","lineNumber":488,"sourceCode":"        from `offset` when `start_line` is unset, which only yields a valid\n        1-indexed gutter for windows the backend actually sliced.\n\n        Args:\n            file_path: Absolute path to the file to read. Must start with `'/'`.\n            offset: Line number to start reading from (0-indexed).\n            limit: Maximum number of lines to read.\n\n        Returns:\n            `ReadResult` with raw (unformatted) content for the requested window,\n                or an error if the file doesn't exist or can't be read.\n\n                Line-number formatting is applied downstream by the filesystem\n                middleware (`format_content_with_line_numbers`), not by backends:\n                it adds the gutter, starts numbering at `offset + 1`, and splits\n                lines longer than 5000 characters into continuation rows\n                (e.g., `5.1`, `5.2`).\n        \"\"\"\n        raise NotImplementedError\n\n    async def aread(\n        self,\n        file_path: str,\n        offset: int = 0,\n        limit: int = 2000,\n    ) -> ReadResult:\n        \"\"\"Async version of read.\"\"\"\n        return await asyncio.to_thread(self.read, file_path, offset, limit)\n\n    def grep(\n        self,\n        pattern: str,\n        path: str | None = None,\n        glob: str | None = None,\n        *,\n        max_count: int | None = None,\n    ) -> \"GrepResult\":","sourceCodeStart":470,"sourceCodeEnd":506,"githubUrl":"https://github.com/langchain-ai/deepagents/blob/a1af029e6e73cb17c36bff823d227747b28e91e1/libs/deepagents/deepagents/backends/protocol.py#L470-L506","documentation":"The base Backend class defines `read` as an abstract method raising NotImplementedError; every usable backend must implement file reading. `read` is the core filesystem capability, so hitting this error means the backend in use is a partial implementation or the abstract base itself. Backends return raw content — line-number formatting is applied downstream, not in `read`.","triggerScenarios":"Calling backend.read(file_path) (directly or via middleware/agent tools) on a subclass that never overrode read; instantiating Backend directly; a write-only or metadata-only custom backend being handed to an agent that then issues a read tool call.","commonSituations":"Building a minimal backend for a demo and the model immediately tries to read a file; a backend subclass with a typo'd method name (e.g. `read_file`) so the abstract slot stays abstract; refactoring that accidentally removed the override.","solutions":["Implement `read(self, file_path, offset=0, limit=2000) -> ReadResult` in your backend subclass.","Verify the method name and signature match the protocol exactly (override must be named `read`).","Switch to a fully implemented backend (filesystem/composite) if your backend intentionally does not support reads, and prevent read tool usage in the agent."],"exampleFix":"// before\nclass WriteOnlyBackend(Backend):\n    def write(self, file_path, content): ...\n    def read_file(self, file_path): ...  # typo: never overrides read\n// after\nclass WriteOnlyBackend(Backend):\n    def write(self, file_path, content): ...\n    def read(self, file_path, offset=0, limit=2000):\n        return ReadResult(content=self._load(file_path))","handlingStrategy":"try-catch","validationCode":"if type(backend).read is Backend.read:\n    raise RuntimeError('backend does not implement read; agent tools will fail')","typeGuard":"def supports_read(backend) -> bool:\n    return type(backend).read is not Backend.read","tryCatchPattern":"try:\n    result = backend.read(file_path)\nexcept NotImplementedError:\n    return ReadResult(error=f'read unsupported by {type(backend).__name__}')","preventionTips":["Smoke-test every backend method (read/ls/write/edit/grep/glob) in CI with a temp file.","Check method names/signatures match the protocol exactly — a renamed override silently stays abstract.","Restrict agent tools to match backend capabilities instead of exposing read against read-only backends."],"tags":["not-implemented","abstract-method","backend-protocol"],"backgroundTag":"not-implemented","analyzedSha":"a1af029e6e73cb17c36bff823d227747b28e91e1","analyzedAt":"2026-08-29T11:43:24.718Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}