langchain-ai/deepagents · error · NotImplementedError

NotImplementedError raised by abstract `upload_files` (backe

Error message

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

What it means

`BackendProtocol.upload_files` is an optional bulk-upload capability with a base stub that raises `NotImplementedError`. Only sandbox-style backends implement it. If a caller (directly, or via `_offload_inline_media` when large media outputs are offloaded to the sandbox) invokes it on a backend that never overrode the method, this error is raised.

Source

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

        Returns:
            List of `FileUploadResponse` objects, one per input file.

                Response order matches input order (`response[i] for files[i]`).

                Check the error field to determine success/failure per file.

        Examples:
            ```python
            responses = sandbox.upload_files(
                [
                    ("/app/config.json", b"{...}"),
                    ("/app/data.txt", b"content"),
                ]
            )
            ```
        """
        raise NotImplementedError

    async def aupload_files(self, files: list[tuple[str, bytes]]) -> list[FileUploadResponse]:
        """Async version of upload_files."""
        return await asyncio.to_thread(self.upload_files, files)

    def download_files(self, paths: list[str]) -> list[FileDownloadResponse]:
        """Download multiple files from the sandbox.

        This API is designed to allow developers to use it either directly or
        by exposing it to LLMs via custom tools.

        Args:
            paths: List of file paths to download.

        Returns:
            List of `FileDownloadResponse` objects, one per input path.

                Response order matches input order (`response[i] for paths[i]`).

View on GitHub (pinned to a1af029e6e)

Solutions

  1. Use a backend that implements `upload_files` (e.g. a sandbox backend like LocalShellBackend)
  2. Guard with a capability check before offloading: verify `type(backend).upload_files is not BackendProtocol.upload_files`
  3. Catch NotImplementedError around upload/offload paths and disable inline-media offloading in that case
  4. Override `upload_files` in your custom backend

Example fix

// before
responses = backend.upload_files([('/app/a.txt', b'hi')])

// after
def can_upload(backend) -> bool:
    return type(backend).upload_files is not BackendProtocol.upload_files
if can_upload(backend):
    responses = backend.upload_files([('/app/a.txt', b'hi')])
else:
    responses = []
Defensive patterns

Strategy: validation

Validate before calling

def supports_upload(backend) -> bool:
    return type(backend).upload_files is not BackendProtocol.upload_files

if not supports_upload(backend):
    disable_media_offload = True

Type guard

def is_upload_capable(backend) -> bool:
    return type(backend).upload_files is not BackendProtocol.upload_files

Try / catch

try:
    responses = backend.upload_files(files)
except NotImplementedError:
    responses = [FileUploadResponse(path=p, error='upload unsupported') for p, _ in files]

Prevention

When it happens

Trigger: Calling `backend.upload_files([(path, bytes), ...])` or `aupload_files` on a backend lacking an override; running media-output offloading (`_offload_inline_media`) against a backend without upload support.

Common situations: Using a state or composite backend where the user expected sandbox-style uploads; custom backend subclasses that implemented `execute`/`read` but not the bulk file APIs; backend swapped by configuration without checking capabilities.

Related errors


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