HKUDS/DeepTutor · error · HTTPException

Archive '{sanitized_filename}' contained no supported files.

Error message

Archive '{sanitized_filename}' contained no supported files.

What it means

Raised by _save_zip_archive after a zip was successfully opened and extracted, but result.extracted was empty — no member of the archive matched the knowledge base's supported file extensions. It is a content-level rejection distinct from a corrupt archive (error 140).

Source

Thrown at deeptutor/api/routers/knowledge.py:296

                tmp.write(chunk)

        try:
            result = safe_extract_zip(
                tmp_path, target_dir, allowed_extensions=allowed_extensions or set()
            )
        except ArchiveTooLargeError as exc:
            raise HTTPException(
                status_code=400,
                detail=f"Rejected archive '{sanitized_filename}': {exc}",
            ) from exc
        except zipfile.BadZipFile as exc:
            raise HTTPException(
                status_code=400,
                detail=f"'{sanitized_filename}' is not a valid zip archive.",
            ) from exc

        if not result.extracted:
            raise HTTPException(
                status_code=400,
                detail=f"Archive '{sanitized_filename}' contained no supported files.",
            )
        return result.extracted
    finally:
        if tmp_path is not None:
            tmp_path.unlink(missing_ok=True)


# Folder organization is purely a human-facing layout: folders are real
# subdirectories under ``raw/`` (no manifest, no retrieval effect). These
# helpers keep user-supplied relative paths safe before they touch the FS.
_BAD_PATH_CHARS = re.compile(r'[\\:*?"<>|\x00-\x1f]')


def _sanitize_path_segment(segment: str) -> str:
    """Sanitize a single folder/file path segment for safe FS use."""
    cleaned = _BAD_PATH_CHARS.sub("", segment).strip().strip(".")

View on GitHub (pinned to 3e82f13042)

Solutions

  1. Inspect the archive (`unzip -l`) and confirm it contains files with the KB's supported extensions
  2. Remove unsupported members and re-zip only the documents you want ingested
  3. If you need a format supported, check the router's extension allow-list / provider format rules before uploading

Example fix

# before
zip contents: photo1.png, photo2.png
# after
zip contents: lecture1.pdf, notes.md
Defensive patterns

Strategy: validation

Validate before calling

SUPPORTED = {'.pdf','.md','.txt','.docx'}

def zip_has_supported(path):
    with zipfile.ZipFile(path) as z:
        return any(Path(n).suffix.lower() in SUPPORTED for n in z.namelist())

Prevention

When it happens

Trigger: Uploading a .zip that contains only unsupported files (e.g. .exe, .png, .txt when only document extensions are supported), or a zip whose supported members were all filtered out by size/path checks.

Common situations: User zips a folder of images or binaries expecting text extraction; nested zips where only the outer archive is inspected; supported files hidden in dot-directories that extraction skips.

Related errors


AI-assisted analysis of HKUDS/DeepTutor@3e82f13042 (2026-08-27). Data as JSON: /api/errors/755c8a19f4adb71b. Report an issue: GitHub.