langchain-ai/deepagents · error · NotImplementedError

NotImplementedError raised by abstract `read` (backend does

Error message

NotImplementedError raised by abstract `read` (backend does not implement `read`)

What it means

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`.

Source

Thrown at libs/deepagents/deepagents/backends/protocol.py:488

        from `offset` when `start_line` is unset, which only yields a valid
        1-indexed gutter for windows the backend actually sliced.

        Args:
            file_path: Absolute path to the file to read. Must start with `'/'`.
            offset: Line number to start reading from (0-indexed).
            limit: Maximum number of lines to read.

        Returns:
            `ReadResult` with raw (unformatted) content for the requested window,
                or an error if the file doesn't exist or can't be read.

                Line-number formatting is applied downstream by the filesystem
                middleware (`format_content_with_line_numbers`), not by backends:
                it adds the gutter, starts numbering at `offset + 1`, and splits
                lines longer than 5000 characters into continuation rows
                (e.g., `5.1`, `5.2`).
        """
        raise NotImplementedError

    async def aread(
        self,
        file_path: str,
        offset: int = 0,
        limit: int = 2000,
    ) -> ReadResult:
        """Async version of read."""
        return await asyncio.to_thread(self.read, file_path, offset, limit)

    def grep(
        self,
        pattern: str,
        path: str | None = None,
        glob: str | None = None,
        *,
        max_count: int | None = None,
    ) -> "GrepResult":

View on GitHub (pinned to a1af029e6e)

Solutions

  1. Implement `read(self, file_path, offset=0, limit=2000) -> ReadResult` in your backend subclass.
  2. Verify the method name and signature match the protocol exactly (override must be named `read`).
  3. Switch to a fully implemented backend (filesystem/composite) if your backend intentionally does not support reads, and prevent read tool usage in the agent.

Example fix

// before
class WriteOnlyBackend(Backend):
    def write(self, file_path, content): ...
    def read_file(self, file_path): ...  # typo: never overrides read
// after
class WriteOnlyBackend(Backend):
    def write(self, file_path, content): ...
    def read(self, file_path, offset=0, limit=2000):
        return ReadResult(content=self._load(file_path))
Defensive patterns

Strategy: try-catch

Validate before calling

if type(backend).read is Backend.read:
    raise RuntimeError('backend does not implement read; agent tools will fail')

Type guard

def supports_read(backend) -> bool:
    return type(backend).read is not Backend.read

Try / catch

try:
    result = backend.read(file_path)
except NotImplementedError:
    return ReadResult(error=f'read unsupported by {type(backend).__name__}')

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of langchain-ai/deepagents@a1af029e6e (2026-08-29). Data as JSON: /api/errors/68d3fad0597b7edd. Report an issue: GitHub.