Exceptions¶
All pyhaul exceptions inherit from HaulError. Transport errors from the
underlying HTTP library (e.g. httpx.ReadTimeout, requests.ConnectionError)
pass through unwrapped — you catch the types you already know.
Exception hierarchy¶
HaulError
├── PartialHaulError
├── UnexpectedStatusError
├── ServerMisconfiguredError
├── ContentRangeError
├── ControlFileError
└── DestinationError
Reference¶
| Exception | When | Retryable? |
|---|---|---|
PartialHaulError |
Stream ended before all bytes arrived. | Yes — call haul() again; progress is saved |
UnexpectedStatusError |
Server returned a non-download status (429, 503, 404, …). | Lets caller decide — check exc.is_transient |
ServerMisconfiguredError |
Server violated HTTP in a way that prevents safe resume. | No |
ContentRangeError |
206 Content-Range doesn't match the requested range. |
Often yes |
ControlFileError |
.part.ctrl is corrupt or version-mismatched. |
Auto-recovers — corrupt checkpoint is discarded on next attempt |
DestinationError |
Destination path can't accommodate sidecar files. | No — fix the path |
| (native) | Transport errors (httpx.ReadTimeout, requests.ConnectionError, etc.) pass through unwrapped. |
Usually yes |
Details¶
pyhaul._types.HaulError
¶
Bases: Exception
Base exception for pyhaul downloader errors.
pyhaul._types.PartialHaulError(reason: str = '')
¶
Bases: HaulError
Stream ended before the full resource was retrieved.
Raised by haul() / haul_async() when the server closes
the connection or the stream ends before all bytes arrive. The
.part and .part.ctrl files persist on disk; a subsequent
call resumes from where this one stopped.
Progress counters live in the :class:HaulState bag, not here.
pyhaul._types.UnexpectedStatusError(status_code: int, headers: TransportHeaders, reason: str = '')
¶
Bases: HaulError
Server returned a non-download HTTP status code.
Carries structured metadata so callers can branch on status codes,
inspect headers (e.g. Retry-After), or log the server's reason
phrase without parsing the message string.
status_code: int = status_code
instance-attribute
¶
The HTTP status code (e.g. 429, 503, 404).
headers: TransportHeaders = headers
instance-attribute
¶
Response headers — immutable, case-insensitive.
reason: str = reason or f'unexpected HTTP {status_code}'
instance-attribute
¶
Human-readable summary, e.g. "unexpected HTTP 429".
is_transient: bool
property
¶
True for 429 (Too Many Requests) and 503 (Service Unavailable).
retry_after: str | None
property
¶
Value of the Retry-After header, if present.
The .headers attribute is a TransportHeaders — an immutable,
case-insensitive mapping with multi-value support and automatic redaction of
sensitive values in logs.
pyhaul._types.ServerMisconfiguredError
¶
Bases: HaulError
The server violated protocol in a way that prevents safe download.
pyhaul._types.ContentRangeError
¶
Bases: HaulError
Content-Range header doesn't match the expected range boundaries.