agentscope-ai/agentscope · critical · RuntimeError

host_cache_dir was replaced before execution.

Error message

host_cache_dir was replaced before execution.

What it means

Raised when host_cache_dir still exists but its (st_dev, st_ino) no longer matches the identity captured in __init__. The directory was deleted and recreated (or swapped to a different filesystem object), so binding it again could mount attacker-controlled or unrelated content.

Source

Thrown at src/agentscope/workspace/_bubblewrap/_bubblewrap_backend.py:495

                ) from exc
            if identity != expected_identity:
                raise RuntimeError(
                    f"{label} was replaced before execution.",
                )

        if self._host_cache_dir is None:
            return
        try:
            identity = self._directory_identity(
                self._host_cache_dir,
                label="host_cache_dir",
            )
        except ValueError as exc:
            raise RuntimeError(
                "host_cache_dir was removed or replaced before execution.",
            ) from exc
        if identity != self._host_cache_identity:
            raise RuntimeError(
                "host_cache_dir was replaced before execution.",
            )

    @staticmethod
    def _directory_identity(
        path: str,
        *,
        label: str,
    ) -> tuple[int, int]:
        """Return a stable identity for a real directory mount source."""
        if os.path.islink(path) or not os.path.isdir(path):
            raise ValueError(f"{label} must be a real directory: {path}")
        stat_result = os.stat(path, follow_symlinks=False)
        return stat_result.st_dev, stat_result.st_ino

    @staticmethod
    def _paths_overlap(left: str, right: str) -> bool:
        """Return whether either real path contains the other."""

View on GitHub (pinned to e90f1c7592)

Solutions

  1. Treat the workspace as invalid: close it and construct a new BubblewrapWorkspace with the same paths
  2. Use in-place cache invalidation (delete contents, keep the directory) instead of recreating the directory
  3. Put the cache on a dedicated volume not subject to replacement

Example fix

# before
# cache reset that breaks identity
shutil.rmtree(cache_dir); os.makedirs(cache_dir)
# after
# in-place clear keeps the directory (and its inode) intact
for entry in os.listdir(cache_dir):
    shutil.rmtree(os.path.join(cache_dir, entry))
Defensive patterns

Strategy: fallback

Validate before calling

null

Type guard

null

Try / catch

except RuntimeError as e:
    if 'host_cache_dir was replaced' in str(e):
        await close_and_recreate_workspace()

Prevention

When it happens

Trigger: rm -rf + mkdir of the cache directory between backend construction and any sandboxed command execution.

Common situations: Recovery routines that 'reset the cache' by recreating it; container image updates replacing the volume underneath a long-lived process.

Related errors


AI-assisted analysis of agentscope-ai/agentscope@e90f1c7592 (2026-08-28). Data as JSON: /api/errors/ff2a19e94a691174. Report an issue: GitHub.