agentscope-ai/agentscope · critical · RuntimeError

{label} was removed or replaced before execution.

Error message

{label} was removed or replaced before execution.

What it means

Before building the bwrap command line, the backend re-stats each configured host mount source and compares dev/ino identity. If _directory_identity raises (path is now a symlink or not a directory), this RuntimeError signals the directory was removed or swapped after the backend was constructed — a security guard against TOCTOU mount substitution.

Source

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

    def _validate_mount_sources(self) -> None:
        """Ensure bind sources were not removed or replaced."""
        for label, path, expected_identity in (
            (
                "host_workdir",
                self._host_workdir,
                self._host_workdir_identity,
            ),
            (
                "host_tmpdir",
                self._host_tmpdir,
                self._host_tmpdir_identity,
            ),
        ):
            try:
                identity = self._directory_identity(path, label=label)
            except ValueError as exc:
                raise RuntimeError(
                    f"{label} was removed or replaced before execution.",
                ) 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

View on GitHub (pinned to e90f1c7592)

Solutions

  1. Recreate the BubblewrapBackend/Workspace with fresh directories after the old ones were removed
  2. Move workspace dirs out of OS-managed temp cleaning policies (e.g. /var/lib/... rather than /tmp)
  3. Avoid deleting/recreating mount source dirs while the workspace object lives

Example fix

# before
shutil.rmtree(host_workdir); os.makedirs(host_workdir)  # mid-session
await ws.run_command('ls')  # RuntimeError
# after
await ws.close()
shutil.rmtree(host_workdir); os.makedirs(host_workdir)
ws = BubblewrapWorkspace(host_workdir=host_workdir)
Defensive patterns

Strategy: fallback

Validate before calling

null

Type guard

null

Try / catch

try:
    await ws.run_command(cmd)
except RuntimeError as e:
    if 'removed or replaced' in str(e):
        ws = await rebuild_workspace()  # reconstruct backend

Prevention

When it happens

Trigger: host_workdir or host_tmpdir (or an ancestor) being deleted and recreated, or replaced by a symlink, between backend construction and a sandbox execution.

Common situations: Cleanup jobs (tmpwatch, systemd-tmpfiles) pruning temp dirs mid-session; concurrent code recreating the workspace directory; an attacker-style symlink swap the guard is designed to catch.

Related errors


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