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 excView on GitHub (pinned to e90f1c7592)
Solutions
- Recreate the BubblewrapBackend/Workspace with fresh directories after the old ones were removed
- Move workspace dirs out of OS-managed temp cleaning policies (e.g. /var/lib/... rather than /tmp)
- 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
- Keep workspace dirs away from tmp-cleaners
- Never rm -rf mount roots while a workspace object is alive
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
- host_cache_dir was removed or replaced before execution.
- Bubblewrap workdir escapes basedir.
- host_cache_dir was replaced before execution.
- {label} must be a real directory: {path}
- Unsafe upload path: {entry.path!r}
AI-assisted analysis of agentscope-ai/agentscope@e90f1c7592 (2026-08-28).
Data as JSON: /api/errors/896da81c6570a2ba.
Report an issue: GitHub.