langchain-ai/deepagents · error · RuntimeError

archive read failed; refusing to overwrite existing history

Error message

archive read failed; refusing to overwrite existing history

What it means

A file-backend wrapper records whether the prerequisite archive read failed; `_ensure_read_succeeded` is checked before any mutating operation (write/edit and their async variants). If the earlier read failed, mutating is refused with this RuntimeError to guarantee the wrapper never overwrites existing conversation history with content based on a stale or missing snapshot.

Source

Thrown at libs/code/deepagents_code/offload_middleware.py:895

        Returns:
            The unchanged backend download responses.
        """
        if any(
            response.error is not None and response.error != FILE_NOT_FOUND
            for response in responses
        ):
            self._read_failed = True
        return responses

    def _ensure_read_succeeded(self) -> None:
        """Raise when a prior archive read failed in this operation.

        Raises:
            RuntimeError: If the prerequisite archive read failed.
        """
        if self._read_failed:
            msg = "archive read failed; refusing to overwrite existing history"
            raise RuntimeError(msg)

    def download_files(self, paths: list[str]) -> list[FileDownloadResponse]:
        """Delegate a synchronous read while recording failures.

        Args:
            paths: Backend paths to read.

        Returns:
            The backend download responses.
        """
        try:
            responses = self._backend.download_files(paths)
        except Exception:
            self._read_failed = True
            raise
        return self._record_response_errors(responses)

    async def adownload_files(self, paths: list[str]) -> list[FileDownloadResponse]:

View on GitHub (pinned to a1af029e6e)

Solutions

  1. Resolve the underlying read failure (connectivity, permissions), then retry the operation through a healthy backend.
  2. Verify the archive path exists and is readable before issuing writes.
  3. If running in a test, seed the fake backend with a successful download response before mutating.

Example fix

// before: blind write after failed read
await backend.awrite(path, content)
// after: confirm read path first
resp = await backend.adownload_files([path])
if resp and resp[0].error is None:
    await backend.awrite(path, content)
Defensive patterns

Strategy: try-catch

Validate before calling

resp = (await backend.adownload_files([path]) or [None])[0]
if resp is not None and resp.error is not None:
    raise ArchiveUnreadable(f"cannot safely mutate {path}: {resp.error}")

Type guard

def can_mutate(backend: RecordingBackend, path: str) -> bool:
    return not backend._read_failed  # or track via a public property

Try / catch

try:
    await backend.awrite(path, content)
except RuntimeError as e:
    if "refusing to overwrite existing history" in str(e):
        await repair_and_reconnect(backend)
        # re-issue the mutation only after a successful read
    raise

Prevention

When it happens

Trigger: Calling `write`, `awrite`, `edit`, or `aedit` through the recording backend after its `download_files`/`adownload_files` returned an error for the target path.

Common situations: Transient archive-backend failure followed by an automatic save/edit attempt in the same session; tests driving mutations without seeding readable archive state; backend connectivity dropped mid-session.

Related errors


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