FoundationAgents/OpenManus · error · ToolError
Failed to write to {path}: {str(e)}
Error message
Failed to write to {path}: {str(e)} What it means
LocalFileOperator.write_file wraps Path.write_text failures in a ToolError. The filesystem cause in '{e}' is usually PermissionError (target dir not writable), FileNotFoundError (parent directory does not exist — write_text does not create parents), or OSError errno 28 (no space left on device).
Source
Thrown at app/tool/file_operators.py:59
class LocalFileOperator(FileOperator):
"""File operations implementation for local filesystem."""
encoding: str = "utf-8"
async def read_file(self, path: PathLike) -> str:
"""Read content from a local file."""
try:
return Path(path).read_text(encoding=self.encoding)
except Exception as e:
raise ToolError(f"Failed to read {path}: {str(e)}") from None
async def write_file(self, path: PathLike, content: str) -> None:
"""Write content to a local file."""
try:
Path(path).write_text(content, encoding=self.encoding)
except Exception as e:
raise ToolError(f"Failed to write to {path}: {str(e)}") from None
async def is_directory(self, path: PathLike) -> bool:
"""Check if path points to a directory."""
return Path(path).is_dir()
async def exists(self, path: PathLike) -> bool:
"""Check if path exists."""
return Path(path).exists()
async def run_command(
self, cmd: str, timeout: Optional[float] = 120.0
) -> Tuple[int, str, str]:
"""Run a shell command locally."""
process = await asyncio.create_subprocess_shell(
cmd, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE
)
try:View on GitHub (pinned to 52a13f2a57)
Solutions
- Create parent directories before writing: Path(path).parent.mkdir(parents=True, exist_ok=True).
- Check writability early: attempt a probe write (or os.access) into the target directory at session start.
- For ENOSPC, clean or enlarge the volume and have the pipeline emit smaller artifacts; check 'df' inside the sandbox.
- Catch ToolError at the caller and surface '{e}' — it distinguishes permission vs missing-parent vs disk-full.
Example fix
# before
await file_op.write_file("/workspace/out/report.md", content) # parent missing -> ToolError
# after
from pathlib import Path
Path("/workspace/out").mkdir(parents=True, exist_ok=True)
await file_op.write_file("/workspace/out/report.md", content) Defensive patterns
Strategy: validation
Validate before calling
from pathlib import Path
p = Path(path)
p.parent.mkdir(parents=True, exist_ok=True)
if not os.access(p.parent, os.W_OK):
raise ToolError(f'{p.parent} is not writable') Try / catch
try:
await file_op.write_file(path, content)
except ToolError as e:
msg = str(e)
if 'No such file or directory' in msg:
Path(path).parent.mkdir(parents=True, exist_ok=True)
await file_op.write_file(path, content)
elif 'Permission' in msg or 'Read-only' in msg:
path = fallback_path_in_writable_dir # pick a writable location
await file_op.write_file(path, content)
else:
raise # e.g. No space left on device — needs cleanup, not retry Prevention
- mkdir -p the parent before every nested write.
- Probe workspace writability at session start.
- Watch disk usage in long sandbox sessions (ENOSPC surfaces here).
When it happens
Trigger: Writing to /workspace/out/report.md when 'out/' was never created; writing into a directory owned by another user or a read-only bind mount; disk/quota exhausted after large generated artifacts.
Common situations: Agent writes to nested output paths without creating them first; container workspace mounted read-only; long sandbox sessions filling a small tmpfs or disk quota.
Related errors
- Failed to write file: {e}
- Source path is a directory but destination is a file: {src_p
- Failed to read {path}: {str(e)}
AI-assisted analysis of FoundationAgents/OpenManus@52a13f2a57 (2026-08-15).
Data as JSON: /api/errors/10b99f8db8ff1da5.
Report an issue: GitHub.