FoundationAgents/OpenManus · error · RuntimeError
Failed to extract file content
Error message
Failed to extract file content
What it means
tar.extractfile(member) returned None, which only happens when the first tar member is not a regular file — directories, symlinks, devices, and fifos have no extractable content stream. Since the code extracts tar.next() (the first member) unconditionally, getting the container to archive a directory or a symlink as the leading member triggers this.
Source
Thrown at app/sandbox/core/sandbox.py:421
Returns:
File content.
Raises:
RuntimeError: If read operation fails.
"""
with tempfile.NamedTemporaryFile() as tmp:
for chunk in tar_stream:
tmp.write(chunk)
tmp.seek(0)
with tarfile.open(fileobj=tmp) as tar:
member = tar.next()
if not member:
raise RuntimeError("Empty tar archive")
file_content = tar.extractfile(member)
if not file_content:
raise RuntimeError("Failed to extract file content")
return file_content.read()
async def cleanup(self) -> None:
"""Cleans up sandbox resources."""
errors = []
try:
if self.terminal:
try:
await self.terminal.close()
except Exception as e:
errors.append(f"Terminal cleanup error: {e}")
finally:
self.terminal = None
if self.container:
try:
await asyncio.to_thread(self.container.stop, timeout=5)View on GitHub (pinned to 52a13f2a57)
Solutions
- Iterate members and pick the first regular file: use member.isfile() instead of blindly taking tar.next().
- Validate at the call site that the source path is a file ('test -f <path>') and reject directories with a clear message before archiving.
- If you intentionally need directories, switch to a directory-aware path (archive every member recursively) rather than single-member extraction.
Example fix
# before
member = tar.next()
if not member:
raise RuntimeError("Empty tar archive")
file_content = tar.extractfile(member)
if not file_content:
raise RuntimeError("Failed to extract file content")
# after
member = None
for m in tar:
if m.isfile():
member = m
break
if member is None:
raise RuntimeError("Archive contains no regular file (directory or symlink only)")
file_content = tar.extractfile(member) Defensive patterns
Strategy: validation
Validate before calling
rc, _, _ = await sandbox.run_command(f'test -f {shlex.quote(path)}')
if rc != 0:
raise ValueError(f'{path} is not a regular file; refusing single-file extraction') Type guard
import tarfile
def first_regular_member(tar: tarfile.TarFile) -> tarfile.TarInfo | None:
return next((m for m in tar if m.isfile()), None) Try / catch
try:
data = extract_from_tar(stream)
except RuntimeError as e:
if 'Failed to extract file content' in str(e):
raise RuntimeError('Source is a directory or symlink; give a regular-file path') from e
raise Prevention
- Validate 'test -f <path>' in the container before copying.
- Prefer member.isfile() over tar.next() when extracting.
- Resolve symlinks in the container ('readlink -f') before archiving.
When it happens
Trigger: Calling the copy/read helper with a path that is a directory: docker get_archive returns the directory entry as the first member and extractfile() yields None for it. Same for a symlink path. Also hit when copying '/workspace' instead of '/workspace/file.txt'.
Common situations: Agent or user passes a folder path (e.g. an output directory) to a file-copy API; a generated file is actually a symlink created by a build step inside the container.
Related errors
- Failed to extract file: {src_path}
- Empty tar archive
- Maximum number of sandboxes ({self.max_sandboxes}) reached
- Failed to ensure Docker image: {config.image}
- Failed to create sandbox: {e}
AI-assisted analysis of FoundationAgents/OpenManus@52a13f2a57 (2026-08-15).
Data as JSON: /api/errors/dff99d7cb1ecabcc.
Report an issue: GitHub.