agentscope-ai/agentscope · error · SkillUploadError

The manifest lists {len(entries)} files but {file_count} wer

Error message

The manifest lists {len(entries)} files but {file_count} were sent.

What it means

SkillUploadError raised when the number of file parts actually streamed does not equal len(manifest.entries). The manifest is the client's declaration of the folder's contents; the server counts the multipart files it receives and refuses to proceed when the two disagree, because a partial upload would silently drop files.

Source

Thrown at src/agentscope/app/_service/_workspace.py:370

        """Check a manifest and return the skill's root directory name.

        Args:
            manifest (`UploadManifest`): The declared upload contents.
            file_count (`int`): How many parts actually arrived.

        Returns:
            `str`: The single top-level directory every path sits under.

        Raises:
            SkillUploadError: If a limit is exceeded, a path is unsafe,
                the paths span more than one root, no ``SKILL.md`` is
                present, or the parts do not match the manifest.
        """
        entries = manifest.entries
        if not entries:
            raise SkillUploadError("The upload contains no files.")
        if file_count != len(entries):
            raise SkillUploadError(
                f"The manifest lists {len(entries)} files but "
                f"{file_count} were sent.",
            )
        if len(entries) > MAX_FILE_COUNT:
            raise SkillUploadError(
                f"A skill may hold at most {MAX_FILE_COUNT} files, "
                f"got {len(entries)}.",
            )

        total = 0
        roots: set[str] = set()
        for entry in entries:
            if entry.size > MAX_FILE_BYTES:
                raise SkillUploadError(
                    f"{entry.path!r} is {entry.size} bytes, over the "
                    f"{MAX_FILE_BYTES}-byte per-file limit.",
                )
            total += entry.size

View on GitHub (pinned to e90f1c7592)

Solutions

  1. Regenerate the manifest immediately before sending so entries and parts come from the same directory snapshot.
  2. Verify each manifest entry has exactly one matching file part (same relative path) in the multipart body.
  3. Remove duplicate or phantom entries introduced by client-side filtering bugs.

Example fix

# before
entries = [UploadEntry(path=f"{root}/{p}", size=...) for p in old_list]
await service.upload_skill(ws, UploadManifest(entries=entries), stream)

# after
files = sorted(root_dir.rglob("*"))
entries = [UploadEntry(path=str(f.relative_to(root_dir.parent)), size=f.stat().st_size) for f in files if f.is_file()]
await service.upload_skill(ws, UploadManifest(entries=entries), stream)
Defensive patterns

Strategy: validation

Validate before calling

parts = {p.filename for p in multipart_files}
declared = {e.path for e in manifest.entries}
assert parts == declared, (parts - declared, declared - parts)

Try / catch

try:
    await service.upload_skill(ws, manifest, stream)
except SkillUploadError as e:
    if "were sent" in str(e):
        # regenerate manifest and retry once
        ...

Prevention

When it happens

Trigger: Calling upload_skill where the multipart form sends more or fewer files than the manifest declares — e.g. the manifest was built before files changed on disk, duplicate/missing form parts, or client code that appends SKILL.md to the manifest but forgets to append the corresponding file part (or vice versa).

Common situations: Files added/deleted between manifest generation and upload; a retry that reuses a stale manifest; bugs in client code mapping directory entries to multipart parts; double-appending an entry.

Related errors


AI-assisted analysis of agentscope-ai/agentscope@e90f1c7592 (2026-08-28). Data as JSON: /api/errors/653bef9f8156ad52. Report an issue: GitHub.