agentscope-ai/agentscope · error · SkillUploadError

{entry.path!r} is larger than its declared {entry.size} byte

Error message

{entry.path!r} is larger than its declared {entry.size} bytes.

What it means

Raised by tar_stream in the workspace service when the bytes actually read from the upload stream for a file exceed the size declared in the manifest (TarInfo) for that entry. It is a SkillUploadError that aborts a streaming skill upload because the tar payload would be malformed (the tar header would no longer match the file data). It protects the server from writing corrupt archives.

Source

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

        Yields:
            `bytes`: The next chunk of the tar archive.

        Raises:
            SkillUploadError: If a part's real length differs from its
                declared size.
        """
        for entry, upload in zip(manifest.entries, files):
            info = tarfile.TarInfo(name=entry.path)
            info.size = entry.size
            info.mtime = 0
            yield info.tobuf(tarfile.GNU_FORMAT)

            written = 0
            while chunk := await upload.read(_CHUNK_SIZE):
                written += len(chunk)
                if written > entry.size:
                    raise SkillUploadError(
                        f"{entry.path!r} is larger than its declared "
                        f"{entry.size} bytes.",
                    )
                yield chunk

            if written != entry.size:
                raise SkillUploadError(
                    f"{entry.path!r} declared {entry.size} bytes but "
                    f"sent {written}.",
                )
            padding = -entry.size % _TAR_BLOCK
            if padding:
                yield b"\0" * padding

        # Two zero blocks mark the end of a tar archive.
        yield b"\0" * (2 * _TAR_BLOCK)

    # ── Git status ─────────────────────────────────────────────────────

View on GitHub (pinned to e90f1c7592)

Solutions

  1. Recompute the manifest entry sizes immediately before uploading so entry.size matches the actual file length
  2. Ensure the skill directory is not being written to (close logs, stop generators) during the upload
  3. If files change frequently, snapshot/copy the skill directory to a temp location and build both manifest and stream from the snapshot
  4. In tests, assert your fixture's declared size equals len(payload) before calling upload_skill

Example fix

# before
info.size = 100  # hardcoded / stale
info = _tar_info(entry, size=100)

# after
size = entry_path.stat().st_size  # measured right before streaming
info = _tar_info(entry, size=size)
Defensive patterns

Strategy: validation

Validate before calling

from pathlib import Path

def check_sizes(base: Path, entries) -> None:
    for e in entries:
        actual = (base / e.path).stat().st_size
        if actual != e.size:
            raise RuntimeError(f"{e.path}: manifest says {e.size}, disk has {actual}; rebuild manifest")

Try / catch

try:
    await upload_skill(...)
except SkillUploadError as e:
    if "larger than its declared" in str(e):
        rebuild_manifest_and_retry()  # sizes drifted; recompute and re-upload

Prevention

When it happens

Trigger: Calling upload_skill (or otherwise consuming tar_stream) where a manifest entry declares entry.size smaller than the real byte length of the corresponding file. Happens when the file changes on disk between manifest creation and streaming, or when the manifest is built with stale/wrong sizes (e.g. stat before truncation, off-by-one size computation, or reusing a manifest across uploads).

Common situations: Skill directory being mutated concurrently (logs written during upload), generating the manifest from metadata that doesn't match the actual file, unit tests that declare a smaller size than the payload they feed (test_declared_size_is_verified).

Related errors


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