langchain-ai/deepagents · critical · RuntimeError
archive rollback failed for {self.path}: {result.error}
Error message
archive rollback failed for {self.path}: {result.error} What it means
`_ArchiveAppend.rollback` restores the archive file to its previous content (rewriting the old bytes or deleting a newly created path). If the backend's `awrite`/`adelete` returns an error, the rollback itself failed and this RuntimeError is raised, meaning the archive may be left in a partially appended state that could not be undone.
Source
Thrown at libs/code/deepagents_code/offload_middleware.py:621
backend: BackendProtocol
path: str
existed: bool
previous: str
async def rollback(self) -> None:
"""Restore the exact archive snapshot from before the append.
Raises:
RuntimeError: If the backend cannot restore the snapshot.
"""
result = (
await self.backend.awrite(self.path, self.previous)
if self.existed
else await self.backend.adelete(self.path)
)
if result.error is not None:
msg = f"archive rollback failed for {self.path}: {result.error}"
raise RuntimeError(msg)
class _ForcedCompactionPlan(NamedTuple):
"""Checkpoint update plus its not-yet-written archive append."""
summarization: SummarizationMiddleware
summary: str
state_cutoff: int
archive: _PendingArchive
def update(self, file_path: str | None) -> dict[str, Any]:
"""Build the summary update with the archive's settled path.
Returns:
State update containing the summary, cutoff, and archive path.
"""
return self.archive.update(file_path)
View on GitHub (pinned to a1af029e6e)
Solutions
- Inspect `result.error` and retry the rollback manually once the backend recovers.
- Restore the archive manually from `self.previous` content (captured before the append).
- Add resilience to the backend (retry policy, stronger consistency) to reduce rollback failures.
Example fix
// before
await backend.adelete(self.path)
// after (retry the compensating delete)
for _ in range(3):
result = await backend.adelete(self.path)
if result.error is None:
break Defensive patterns
Strategy: try-catch
Validate before calling
// cannot fully pre-validate; check backend writability beforehand probe = await backend.awrite(probe_path, b"") assert probe.error is None, "archive backend not writable; rollback would fail"
Type guard
def rollback_capable(append: _ArchiveAppend) -> bool:
return append.previous is not None or not append.existed Try / catch
try:
await offload(thread_id)
except RuntimeError as e:
if "archive rollback failed" in str(e):
await manually_restore_archive(archive_path, captured_previous)
raise Prevention
- Capture archive content before appends so manual restoration is always possible.
- Use a strongly consistent archive backend to avoid delete-after-write lag.
- Monitor storage quota and permissions; rollbacks commonly fail for the same reason the write path degrades.
When it happens
Trigger: A checkpoint reservation fails after the archive append was written and the compensating `adelete`/`awrite` of the previous content returns an error (storage outage, permission change, eventual-consistency lag).
Common situations: Transient storage failures during offload cancellation; distributed backends where the just-written object is not yet visible for delete; quota exhaustion mid-offload.
Related errors
- archive backend returned no response for {path}
- archive read failed for {path}: {response.error}
- archive read failed; refusing to overwrite existing history
- Offload server returned an invalid cancellation acknowledgem
- Offload server completed without a typed result.
AI-assisted analysis of langchain-ai/deepagents@a1af029e6e (2026-08-29).
Data as JSON: /api/errors/2c5f6e07e786d9aa.
Report an issue: GitHub.