Skip to content

Error Handling

aiogzip normalizes errors into a small, stable taxonomy. The engine backing decompression (stdlib zlib or zlib-ng from the [fast] extra) never changes which exception type you see: engine-specific errors are caught internally and re-raised uniformly, so except clauses written against stdlib behavior keep working when the fast engine is installed.

Taxonomy

Situation Raises Notes
Corrupt or malformed gzip data gzip.BadGzipFile Bad magic/header, CRC mismatch, wrong ISIZE, truncated or garbled deflate stream. Identical across engines.
Underlying I/O failure OSError Missing file, permission denied, disk errors — whatever the OS raised.
max_decompressed_size exceeded OSError (not BadGzipFile) Message starts with "decompressed output exceeded max_decompressed_size".
Wrong argument types / values TypeError / ValueError Raised eagerly at the call with a corrective message.
Operations on a closed file ValueError Matches io module conventions.
Reading a write-mode file (or vice versa) OSError e.g. "File not open for reading".

gzip.BadGzipFile subclasses OSError, so order your handlers from specific to general:

import gzip

import aiogzip

try:
    data = await aiogzip.read("untrusted.gz", max_decompressed_size=100 * 2**20)
except gzip.BadGzipFile:
    ...  # corrupt or hostile input: reject the file
except OSError as exc:
    ...  # I/O failure, or the decompression cap tripped (see below)

Telling the decompression cap apart from corruption

A stream that exceeds max_decompressed_size (a decompression bomb, or just a bigger file than expected) raises a plain OSError, not BadGzipFile — the data may be perfectly valid gzip; it is the output budget that was exceeded. Because the cap error is not a BadGzipFile, the handler split above distinguishes the two cases by exception type alone. If you need to single the cap out from real I/O errors within the OSError branch, match on its stable message prefix:

try:
    data = await aiogzip.read("untrusted.gz", max_decompressed_size=100 * 2**20)
except gzip.BadGzipFile:
    raise  # corrupt input: not the cap
except OSError as exc:
    if str(exc).startswith("decompressed output exceeded max_decompressed_size"):
        ...  # over budget: maybe retry with a larger cap
    else:
        raise

Where errors surface

Streaming helpers validate lazily where the work happens: the iterator returned by decompress_chunks() raises BadGzipFile only as the corrupt region is consumed, and complete trailer validation happens when the iterator is exhausted. verify() and inspect() scan the whole stream eagerly and raise before returning a result. See Processing untrusted gzip input for a full defensive-reading recipe.