agentscope-ai/agentscope · error · RuntimeError
Failed to expand skill archive: {result.stderr.decode('utf-8
Error message
Failed to expand skill archive: {result.stderr.decode('utf-8', 'replace')} What it means
Raised by add_skill_archive when the subprocess used to extract the uploaded archive (into a staging directory, with a byte cap) exits non-zero. The RuntimeError wraps the extractor's stderr, so the message tells you why unpacking failed: unsupported format, corrupt archive, or extraction size limit exceeded.
Source
Thrown at src/agentscope/workspace/_local_workspace.py:923
self.workdir,
f".skill-staging-{_generate_id()}",
)
archive_path = f"{staging}.{'tar.gz' if fmt == 'tar.gz' else fmt}"
try:
await self._backend.write_stream(archive_path, stream)
result = await self._backend.exec_shell(
[
self._python_command,
"-c",
_EXTRACT_ARCHIVE_SHIM,
archive_path,
staging,
fmt,
str(max_extracted_bytes),
],
)
if not result.ok():
raise RuntimeError(
f"Failed to expand skill archive: "
f"{result.stderr.decode('utf-8', 'replace')}",
)
await self.add_skill(
await self._find_skill_root(staging),
agent_id=agent_id,
)
finally:
await self._backend.delete_path(staging)
await self._backend.delete_path(archive_path)
async def remove_skill(
self,
name: str,
*,
agent_id: str | None = None,
) -> None:
"""Remove a skill from the workspace by its agent-facing name.View on GitHub (pinned to e90f1c7592)
Solutions
- Re-create the archive with a standard format matching fmt (e.g. tar czf skill.tar.gz skill-dir) and retry.
- Read result.stderr in the exception message to identify the exact extractor failure (format vs size limit).
- If the archive is legitimately large, raise max_extracted_bytes when calling add_skill_archive.
- Verify archive integrity locally (tar -tzf skill.tar.gz / unzip -t skill.zip) before uploading.
Example fix
# before
await ws.add_skill_archive(data, fmt="tar.gz") # stderr: 'unsupported format'
# after
import tarfile, io
buf = io.BytesIO()
with tarfile.open(fileobj=buf, mode="w:gz") as tf:
tf.add("my-skill")
await ws.add_skill_archive(buf.getvalue(), fmt="tar.gz") Defensive patterns
Strategy: try-catch
Validate before calling
import tarfile, zipfile
def archive_is_sound(data: bytes, fmt: str) -> bool:
import io
if fmt == "zip":
return zipfile.ZipFile(io.BytesIO(data)).testzip() is None
with tarfile.open(fileobj=io.BytesIO(data), mode="r:*") as tf:
return len(tf.getnames()) > 0 Try / catch
try:
await ws.add_skill_archive(data, fmt=fmt)
except RuntimeError as e:
if "Failed to expand skill archive" in str(e):
raise SkillArchiveError(str(e)) from e
raise Prevention
- Test archives locally (tar -tzf / unzip -t) before upload.
- Create archives with standard gzip/zip, not exotic compressors.
- Size the archive and pass a matching max_extracted_bytes.
When it happens
Trigger: Calling add_skill_archive with a corrupt/truncated archive, an archive format not supported by the extractor (fmt mismatch), or an archive whose extracted contents exceed max_extracted_bytes (deflate bombs / large skills).
Common situations: Uploading .zip files renamed to .tar.gz, archives created with exotic compression (e.g. zstd) unsupported by the extractor, truncated uploads, or hitting the configured extraction byte limit with large model files inside the skill.
Related errors
- write to {path!r} failed: {command[0]} exited {exit_code}: {
- Invalid skill at {skill_path!r}: missing or malformed SKILL.
- Skill path {skill_path!r} resolves outside skills_dir.
- One or more tool calls raised an exception
- Input validation failed for tool '{tool_call.name}': {e.mess
AI-assisted analysis of agentscope-ai/agentscope@e90f1c7592 (2026-08-28).
Data as JSON: /api/errors/562560c0be481fa7.
Report an issue: GitHub.