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 (408, 429, 5xx, 404, …). | Lets caller decide — check exc.is_transient / exc.is_server_error |
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 |
TransportError |
Translated adapter / client I/O failure (timeout, TLS, reset, …) before pyhaul can complete the response. | 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 when the status usually indicates a temporary condition worth retrying.
Includes common overload / upstream / CDN signals (e.g. 408, 425,
429, 5xx gateway and origin errors, and Cloudflare 520/522/524).
For any HTTP 5xx without branching on this set, see :attr:is_server_error.
is_server_error: bool
property
¶
True for HTTP 5xx responses (status 500 ≤ code ≤ 599).
retry_after: str | None
property
¶
Raw Retry-After header value, if present (seconds or HTTP-date string).
retry_after_seconds: float | None
property
¶
Seconds until retry per Retry-After, or None if absent/unparsable.
Accepts delay-seconds (integer) and HTTP-date forms (RFC 9110 §10.2.3).
For dates in the past, returns 0.0. Parsing only — pyhaul does not retry or cap sleeps.
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.
pyhaul._types.ControlFileError
¶
Bases: HaulError
The control file is corrupt, unreadable, or inconsistent with the part file.
pyhaul._types.DestinationError
¶
Bases: HaulError
The destination path cannot accommodate sidecar files (.part, .part.ctrl).
pyhaul.transport.errors.TransportError
¶
Bases: HaulError
Base class for failures surfaced by a :class:pyhaul.transport.TransportSession.
pyhaul.transport.errors.TransportConnectionError(message: str)
¶
Bases: TransportError, ConnectionError
Network-level failure (DNS, refused connection, reset, timeout, ...).
Subclasses builtin :exc:ConnectionError (and thus :exc:OSError) as well as
:class:TransportError.
pyhaul.transport.errors.TransportTLSError
¶
Bases: TransportError
TLS / certificate verification failure.
pyhaul.transport.errors.TransportHTTPError(message: str, *, status_code: int | None = None)
¶
pyhaul.transport.errors.TransportUnsupportedError
¶
Bases: TransportError
The transport or server cannot satisfy a request (capability / policy).