langchain-ai/deepagents · error · RuntimeError
archive backend returned no response for {path}
Error message
archive backend returned no response for {path} What it means
`_previous_content` reads the archived conversation snapshot from the archive backend via `adownload_files([path])` before appending. If the backend returns an empty response list, the code cannot distinguish 'missing' (empty list vs FILE_NOT_FOUND) and raises RuntimeError rather than silently treating history as absent, which would risk overwriting existing archives.
Source
Thrown at libs/code/deepagents_code/offload_middleware.py:571
self.summary,
file_path,
self.state_cutoff,
self.session_id,
)
async def _previous_content(self, path: str) -> tuple[bool, str]:
"""Read the archive snapshot needed to undo an uncommitted append.
Returns:
Whether the archive existed and its prior UTF-8 content.
Raises:
RuntimeError: If the backend cannot return the archive snapshot.
"""
responses = await self.backend.adownload_files([path])
if not responses:
msg = f"archive backend returned no response for {path}"
raise RuntimeError(msg)
response = responses[0]
if response.error == FILE_NOT_FOUND:
return False, ""
if response.error is not None:
msg = f"archive read failed for {path}: {response.error}"
raise RuntimeError(msg)
content = response.content or b""
return True, content.decode("utf-8")
async def write(self) -> _ArchiveAppend | None:
"""Append staged messages and retain enough state for rollback.
Returns:
The reversible append, or `None` when the SDK could not write it.
"""
path = self.summarization._get_history_path(self.session_id)
existed, previous = await self._previous_content(path)
guard = cast("BackendProtocol", _ArchiveReadGuard(self.backend))View on GitHub (pinned to a1af029e6e)
Solutions
- Fix the backend so it returns a FileDownloadResponse with `error` set instead of returning an empty list.
- Check backend connectivity/permissions so `adownload_files` can actually fetch the archive path.
- If a wrapper intentionally drops responses, make it surface FILE_NOT_FOUND for missing keys.
Example fix
// before (custom backend)
async def adownload_files(self, paths):
return [r for r in self._fetch(paths) if r is not None]
// after
async def adownload_files(self, paths):
return self._fetch(paths) # return one response per path, with error set on failure Defensive patterns
Strategy: type-guard
Validate before calling
responses = await backend.adownload_files([path])
if not responses:
raise BackendMisconfigured(f"{type(backend).__name__} returned no responses for {path}") Type guard
def has_download_response(responses: list[FileDownloadResponse] | None) -> bool:
return bool(responses) and len(responses) > 0 Try / catch
try:
await offload(thread_id)
except RuntimeError as e:
if "returned no response" in str(e):
check_backend_health(backend) # fix the custom/stub backend
raise Prevention
- Contract-test custom backends: one response per requested path, errors set on the response, never an empty list.
- Avoid wrapper backends that silently drop failed downloads.
- Run offload smoke tests against your storage backend before production.
When it happens
Trigger: A misbehaving or stubbed backend whose `adownload_files` returns `[]` for the archive path; a custom CompositeBackend child that swallows responses; a storage layer returning no rows without an error code.
Common situations: Custom archive backends (S3/DB-backed) that return empty lists on transient store errors; test fakes that forget to enqueue a response; backend wrappers that filter out failed downloads instead of reporting them as error responses.
Related errors
- archive read failed for {path}: {response.error}
- archive rollback failed for {self.path}: {result.error}
- Offload operation must use the agent's composite backend
- archive read failed; refusing to overwrite existing history
- Agent backend did not publish its offload operation; /offloa
AI-assisted analysis of langchain-ai/deepagents@a1af029e6e (2026-08-29).
Data as JSON: /api/errors/7a75892684396d3e.
Report an issue: GitHub.