You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Corrupt, truncated or encrypted package raises BadZipFile instead of PackageNotFoundError #65
Opening a file that is not a valid zip — truncated download, encrypted (password-protected) document, or plain garbage — raises zipfile.BadZipFile straight out of the standard library instead of the library's own PackageNotFoundError.
Reproduction
Document(io.BytesIO(b"not a zip file at all"))
# zipfile.BadZipFile: File is not a zip fileraw=pathlib.Path(".../default.docx").read_bytes()
Document(io.BytesIO(raw[: len(raw) //2]))
# zipfile.BadZipFile: File is not a zip file
docx.opc.exceptions.PackageNotFoundError already exists and is raised when the path does not exist, so callers reasonably write except PackageNotFoundError and are then surprised by a BadZipFile that leaks an implementation detail of the physical package layer.
Why it matters
Anything ingesting user-supplied documents hits this immediately. A password-protected .docx is an OLE compound file, not a zip, so it lands here too — and that is a common enough input that it deserves a clear error rather than a stdlib exception.
Scope
Wrap the zip open in docx/opc/phys_pkg.py and re-raise BadZipFile as PackageNotFoundError with a message naming the likely cause
Chain the original exception (raise ... from err) so the underlying detail is not lost
Detect the OLE compound-file signature (D0 CF 11 E0 A1 B1 1A E1) and raise a distinct, clearer error for encrypted/password-protected documents — telling a user their file is encrypted is much more useful than "not a zip file"
Unit tests for truncated, garbage, and OLE-signature inputs
Notes
Upstream PR python-openxml#1562 wraps corrupt/truncated/encrypted zip read errors in PackageNotFoundError, unmerged since June 2026. The encrypted-document distinction is not in that PR and is the more valuable half.
Activity