agentscope-ai/agentscope · error · ValueError
host_cache_dir must be a directory.
Error message
host_cache_dir must be a directory.
What it means
BubblewrapBackend validates that host_cache_dir is a directory after creating it. If the path exists but is not a directory (e.g. a regular file, socket, or symlink to a file), makedirs succeeds as a no-op and this ValueError is raised, because the cache must be bind-mounted as a directory.
Source
Thrown at src/agentscope/workspace/_bubblewrap/_bubblewrap_backend.py:109
cache_dir = os.path.abspath(host_cache_dir)
if os.path.lexists(cache_dir) and os.path.islink(cache_dir):
raise ValueError("host_cache_dir must not be a symbolic link.")
cache_realpath = os.path.realpath(cache_dir)
self._host_cache_dir = cache_realpath
mount_sources.append(("host_cache_dir", cache_realpath))
for index, (left_name, left_path) in enumerate(mount_sources):
for right_name, right_path in mount_sources[index + 1 :]:
if self._paths_overlap(left_path, right_path):
raise ValueError(
f"{left_name} must not overlap {right_name}.",
)
if cache_dir is not None:
cache_created = not os.path.lexists(cache_dir)
os.makedirs(cache_dir, mode=0o700, exist_ok=True)
if cache_created:
os.chmod(cache_dir, 0o700)
if not os.path.isdir(cache_dir):
raise ValueError("host_cache_dir must be a directory.")
assert self._host_cache_dir is not None
self._host_cache_identity = self._directory_identity(
self._host_cache_dir,
label="host_cache_dir",
)
self._workdir = workdir
self._share_net = share_net
self._env = dict(env or {})
async def getcwd(self) -> str:
"""Return the backend's default working directory."""
return self._workdir
async def exec_shell(
self,
command: list[str],
*,
cwd: str | None = None,View on GitHub (pinned to e90f1c7592)
Solutions
- Remove or rename the non-directory entry at the cache path (rm /path/to/cache)
- Point cache_dir at a real (or not-yet-existing) directory path
- Ensure no symlink in the path resolves to a file
Example fix
# before
backend = BubblewrapBackend(cache_dir='/srv/cache') # /srv/cache is a file
# after
import os, shutil
if os.path.lexists('/srv/cache') and not os.path.isdir('/srv/cache'):
os.remove('/srv/cache')
backend = BubblewrapBackend(cache_dir='/srv/cache') Defensive patterns
Strategy: validation
Validate before calling
import os
if os.path.lexists(cache_dir) and not os.path.isdir(cache_dir):
os.remove(cache_dir) # or fail fast with a clear message Type guard
null
Try / catch
try:
BubblewrapBackend(cache_dir=p)
except ValueError as e:
if 'must be a directory' in str(e): ... Prevention
- Ensure the cache path is not pre-created as a file by deployment tooling
When it happens
Trigger: Passing cache_dir pointing at an existing regular file, FIFO, or a dangling/non-directory filesystem entry.
Common situations: A stale cache file left at the expected cache path, or a symlink chain where the final target is a file; tooling that 'touches' the cache path before the library runs.
Related errors
- host_cache_dir must not be a symbolic link.
- host_cache_dir must be a real directory.
- Path {path_file} exists but is not a file.
- File {path_file} does not exist.
- {left_name} must not overlap {right_name}.
AI-assisted analysis of agentscope-ai/agentscope@e90f1c7592 (2026-08-28).
Data as JSON: /api/errors/34ebcb3a91e056bb.
Report an issue: GitHub.