HKUDS/DeepTutor · error · HTTPException
'{sanitized_filename}' is not a valid zip archive.
Error message
'{sanitized_filename}' is not a valid zip archive. What it means
Raised by _save_zip_archive when Python's zipfile module throws BadZipFile while opening/extracting an uploaded archive. The file's name/extension suggests a .zip but its content is corrupt, truncated, or not a zip at all (e.g. a renamed file or an interrupted upload). The router converts it to HTTP 400 so the client knows the payload itself is invalid.
Source
Thrown at deeptutor/api/routers/knowledge.py:290
status_code=400,
detail=(
f"Archive '{sanitized_filename}' exceeds maximum size limit of "
f"{format_bytes_human_readable(max_size)}"
),
)
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.View on GitHub (pinned to 3e82f13042)
Solutions
- Re-download or regenerate the archive and verify it opens locally with `unzip -t file.zip`
- Check the upload pipeline (proxy body limits, multipart handling) is not truncating the file
- If the file is not meant to be an archive, upload it with its real extension so it bypasses zip handling
- Verify Content-Length matches the actual file size before uploading
Example fix
# before
files = {'file': open('notes.zip','rb')} # notes.zip is actually a PDF
requests.post(url, files=files)
# after
import zipfile
with open('notes.zip','rb') as f:
assert zipfile.is_zipfile(f), 'not a zip'
requests.post(url, files=files) Defensive patterns
Strategy: validation
Validate before calling
import zipfile
def is_valid_zip(path):
with open(path,'rb') as f:
return zipfile.is_zipfile(f) and zipfile.ZipFile(f).testzip() is None Try / catch
try: resp = upload(files)
except HTTPError as e:
if e.response.status_code == 400 and 'not a valid zip archive' in e.response.text(): repair_and_retry()
else: raise Prevention
- Run zipfile.is_zipfile() before uploading
- Verify archive integrity with testzip() client-side
- Confirm uploads complete (match Content-Length) before submitting
When it happens
Trigger: POST to the knowledge-base upload endpoint with a file whose extension triggers zip handling but whose bytes fail zipfile.ZipFile parsing — corrupt download, HTML error page saved as .zip, multipart upload truncated by a proxy, or double-compressed/encrypted archive.
Common situations: Client uploads a file renamed to .zip; archive corrupted during transfer; a 0-byte zip from a failed disk write; test fixtures generating invalid zips.
Related errors
- Archive '{sanitized_filename}' exceeds maximum size limit of
- Archive '{sanitized_filename}' contained no supported files.
- Rejected archive '{sanitized_filename}': {exc}
- File '{sanitized_filename}' exceeds maximum size limit of {s
- Validation failed for file '{original_filename}': {format_ex
AI-assisted analysis of HKUDS/DeepTutor@3e82f13042 (2026-08-27).
Data as JSON: /api/errors/5279b92ca0331d1c.
Report an issue: GitHub.