bytedance/deer-flow · warning · HTTPException

Skill archive member is too large to preview

Error message

Skill archive member is too large to preview

What it means

HTTP 413 from _read_skill_archive_member: the ZIP entry's declared uncompressed file_size in its ZipInfo header exceeds MAX_SKILL_ARCHIVE_MEMBER_BYTES (16 MiB, artifacts.py:38). The header check happens before any decompression so a zip-bomb-sized member is refused without spending CPU/bytes on it.

Source

Thrown at backend/app/gateway/routers/artifacts.py:221

    )
    return ranged_content, 206, headers


def is_text_file_by_content(path: Path, sample_size: int = 8192) -> bool:
    """Check if file is text by examining content for null bytes."""
    try:
        with open(path, "rb") as f:
            chunk = f.read(sample_size)
            # Text files shouldn't contain null bytes
            return b"\x00" not in chunk
    except Exception:
        return False


def _read_skill_archive_member(zip_ref: zipfile.ZipFile, info: zipfile.ZipInfo) -> bytes:
    """Read a .skill archive member while enforcing an uncompressed size cap."""
    if info.file_size > MAX_SKILL_ARCHIVE_MEMBER_BYTES:
        raise HTTPException(status_code=413, detail="Skill archive member is too large to preview")

    chunks: list[bytes] = []
    total_read = 0
    with zip_ref.open(info, "r") as src:
        while chunk := src.read(_SKILL_ARCHIVE_READ_CHUNK_SIZE):
            total_read += len(chunk)
            if total_read > MAX_SKILL_ARCHIVE_MEMBER_BYTES:
                raise HTTPException(status_code=413, detail="Skill archive member is too large to preview")
            chunks.append(chunk)
    return b"".join(chunks)


def _extract_file_from_skill_archive(zip_path: Path, internal_path: str) -> bytes | None:
    """Extract a file from a .skill ZIP archive.

    Args:
        zip_path: Path to the .skill file (ZIP archive).
        internal_path: Path to the file inside the archive (e.g., "SKILL.md").

View on GitHub (pinned to 1dd6ba1acb)

Solutions

  1. Remove the oversized member from the skill pack and rebuild the .skill archive
  2. Split large assets out of the skill; reference them by URL or install step instead of bundling
  3. If you are the consumer, preview other members — only the oversized entry is refused
Defensive patterns

Strategy: validation

Validate before calling

import zipfile

MAX_SKILL_ARCHIVE_MEMBER_BYTES = 16 * 1024 * 1024

def member_within_cap(zip_path: str, internal_path: str) -> bool:
    with zipfile.ZipFile(zip_path) as z:
        return z.getinfo(internal_path).file_size <= MAX_SKILL_ARCHIVE_MEMBER_BYTES

Try / catch

if resp.status_code == 413 and "skill archive member" in resp.text.lower():
    skip_preview(internal_path)  # show metadata only

Prevention

When it happens

Trigger: GET artifact preview for a .skill archive whose member (e.g. bundled model, dataset, or vendored dependency) declares >16 MiB uncompressed size in the ZIP central directory.

Common situations: Skill packs vendoring large binaries or node_modules-like trees, users zipping whole working directories into .skill files, malicious/naive archives with inflated headers.

Related errors


AI-assisted analysis of bytedance/deer-flow@1dd6ba1acb (2026-08-14). Data as JSON: /api/errors/019dfe09e2fcb4e2. Report an issue: GitHub.