FoundationAgents/OpenManus · error · ToolError

Failed to read {path}: {str(e)}

Error message

Failed to read {path}: {str(e)}

What it means

LocalFileOperator.read_file wraps any exception from Path.read_text(encoding='utf-8') in a ToolError with the path and cause. Typical underlying causes: FileNotFoundError (no such file), IsADirectoryError, PermissionError, and UnicodeDecodeError when the file is binary or in another encoding — the operator hardcodes utf-8.

Source

Thrown at app/tool/file_operators.py:52

    async def run_command(
        self, cmd: str, timeout: Optional[float] = 120.0
    ) -> Tuple[int, str, str]:
        """Run a shell command and return (return_code, stdout, stderr)."""
        ...


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

View on GitHub (pinned to 52a13f2a57)

Solutions

  1. Check existence first: await operator.exists(path) (and is_directory) before read_file, and give a clear message when missing.
  2. For encoding failures shown in '{e}', re-save the file as UTF-8 or subclass/extend the operator with the right encoding.
  3. Verify the producing step succeeded before reading its output (exit code / output check), so you never read a file that was never written.
  4. Catch ToolError at the agent layer and feed the message back so the next action corrects the path.

Example fix

# before
text = await file_op.read_file("/workspace/out/report.txt")

# after
path = "/workspace/out/report.txt"
if not await file_op.exists(path):
    raise ToolError(f"{path} not found; did the previous step finish?")
text = await file_op.read_file(path)
Defensive patterns

Strategy: try-catch

Validate before calling

if not await file_op.exists(path):
    raise ToolError(f'{path} does not exist')
if await file_op.is_directory(path):
    raise ToolError(f'{path} is a directory, not a file')

Try / catch

try:
    text = await file_op.read_file(path)
except ToolError as e:
    msg = str(e)
    if 'No such file' in msg:
        ...  # regenerate or correct path
    elif 'codec' in msg or 'UnicodeDecode' in msg:
        ...  # binary/non-utf8 file — read bytes or fix encoding
    else:
        raise

Prevention

When it happens

Trigger: Reading a path that was never created by a previous step; reading a directory path; reading files on a read-only mount without permission; reading CSV/Excel artifacts saved as non-UTF-8 (e.g. latin-1 exports) or binary formats.

Common situations: Agent assumes an output file exists after a step that silently failed; workspace mounted with restrictive permissions; user-supplied files in legacy encodings.

Related errors


AI-assisted analysis of FoundationAgents/OpenManus@52a13f2a57 (2026-08-15). Data as JSON: /api/errors/abbee9e06b8c19a2. Report an issue: GitHub.