dataretrieval.exceptions
Exception taxonomy for dataretrieval.
Every service module (nwis, wqp, nldi, waterdata, nadp,
streamstats) raises a subclass of DataRetrievalError when a request
fails, so one except dataretrieval.DataRetrievalError catches them all –
including connection-level failures (timeouts, DNS, refused connections), which
are wrapped as NetworkError with the underlying httpx exception on
__cause__.
Most failures are an HTTPError carrying the response .status_code,
of which TransientError (429 / 5xx) is the retryable subset. The rest
aren’t a plain status: RequestTooLarge (with URLTooLong /
Unchunkable), NetworkError (a failed connection, per above),
and NoSitesError. error_for_status() maps a status to its type.
This module has no third-party runtime dependencies – httpx is imported only
for type checking – so any module can import it without pulling in pandas / httpx
and without risking an import cycle.
- exception dataretrieval.exceptions.DataRetrievalError[source]
Bases:
ExceptionBase class for every failed-request error in
dataretrieval.Catch it to handle any USGS or EPA service failure uniformly, and branch on the read-anywhere fields below without needing the concrete subclass:
try: df, md = dataretrieval.waterdata.get_daily(...) except dataretrieval.DataRetrievalError as e: if e.retryable: # 429 / 5xx / connection failure time.sleep(e.retry_after or backoff) ... # re-issue the request elif e.status_code == 404: # ``None`` unless an HTTP status error ... else: raise
Connection-level failures (timeouts, DNS) are wrapped as
NetworkError, so this single clause covers them too.- retry_after: float | None = None
Seconds the server asked us to wait before retrying (its
Retry-Afterheader), orNonewhen it gave no hint. Set byTransientError.
- retryable: ClassVar[bool] = False
Whether re-issuing the same request might succeed –
Truefor the transient HTTP statuses (429 / 5xx,TransientError) and for connection failures (NetworkError);Falseotherwise.
- exception dataretrieval.exceptions.HTTPError(message: str, *, status_code: int)[source]
Bases:
DataRetrievalErrorThe service returned an error HTTP status.
The numeric status is on
status_code; branch on it, e.g.except HTTPError as e: ... if e.status_code == 404.TransientError(429 / 5xx) is the retryable subset, and is itself anHTTPError. The one exception to “a status is anHTTPError” is a request the service rejects as too long: it surfaces asURLTooLong(aRequestTooLarge), not anHTTPError– so catchDataRetrievalErrorto be certain of spanning every failure. Seeerror_for_status()for the full mapping.- Parameters:
message (str) – Human-readable error message.
status_code (int) – The HTTP status the service returned.
- exception dataretrieval.exceptions.NetworkError[source]
Bases:
DataRetrievalErrorThe request never completed a round-trip to the service – a DNS failure, refused connection, or timeout – so no HTTP response arrived to classify.
Wraps the underlying
httpxtransport exception, preserved on__cause__. Worth retrying (retryableisTrue), but carries no.status_codebecause no response came back.- retryable: ClassVar[bool] = True
Whether re-issuing the same request might succeed –
Truefor the transient HTTP statuses (429 / 5xx,TransientError) and for connection failures (NetworkError);Falseotherwise.
- exception dataretrieval.exceptions.NoSitesError(url: httpx.URL)[source]
Bases:
DataRetrievalErrorA request succeeded (HTTP 200) but matched no sites/data.
A no-data result is normally not an error: the modern getters (
waterdata,wqp,nldi) return an emptyDataFrame. Only the deprecatednwis(waterservices) path still raises this.
- exception dataretrieval.exceptions.RateLimited(message: str, *, status_code: int | None = None, retry_after: float | None = None)[source]
Bases:
TransientErrorA request was rejected with HTTP 429 (too many requests).
- _DEFAULT_STATUS: ClassVar[int] = 429
Canonical status a concrete transient stamps when built without an explicit
status_code(RateLimited= 429,ServiceUnavailable= 503).TransientErroritself is abstract and sets none, so constructing it bare requiresstatus_code.
- exception dataretrieval.exceptions.RequestTooLarge[source]
Bases:
DataRetrievalErrorThe request is too large for the service to satisfy.
Base for the two ways that happens; catch it to handle either:
URLTooLong(a single request rejected for length) andUnchunkable(a Water Data call the chunker could not split small enough to fit).
Bases:
TransientErrorA request was rejected with a server error (HTTP 5xx).
Raised by both the legacy
querypath and the Water Data path, so a 5xx surfaces as one type whichever subsystem issued the request..status_codeholds the actual 5xx; it falls back to 503 only on a bare hand-construction.Canonical status a concrete transient stamps when built without an explicit
status_code(RateLimited= 429,ServiceUnavailable= 503).TransientErroritself is abstract and sets none, so constructing it bare requiresstatus_code.
- exception dataretrieval.exceptions.TransientError(message: str, *, status_code: int | None = None, retry_after: float | None = None)[source]
Bases:
HTTPErrorA 429 or 5xx the server may serve on a later try –
RateLimitedfor 429,ServiceUnavailablefor 5xx.This only classifies the condition; it does not itself retry. Whether to retry is up to the calling path: a single-shot request raises it for the caller to handle (e.g. wait
retry_afterseconds, then re-issue), while the Water Data chunker retries and resumes automatically.- Parameters:
message (str) – Human-readable error message.
status_code (int, optional) – The HTTP status the service returned. Defaults to the leaf’s canonical code (429 / 503) when omitted;
error_for_status()always passes the real status.retry_after (float, optional) – Seconds to wait before retrying, parsed from the
Retry-Afterresponse header;Nonewhen the header is absent or unparseable.
- _DEFAULT_STATUS: ClassVar[int]
Canonical status a concrete transient stamps when built without an explicit
status_code(RateLimited= 429,ServiceUnavailable= 503).TransientErroritself is abstract and sets none, so constructing it bare requiresstatus_code.
- retryable: ClassVar[bool] = True
Whether re-issuing the same request might succeed –
Truefor the transient HTTP statuses (429 / 5xx,TransientError) and for connection failures (NetworkError);Falseotherwise.
- exception dataretrieval.exceptions.URLTooLong[source]
Bases:
RequestTooLargeA single request URL was too long for the service.
Raised on the legacy
querypath (which sends one un-chunked request), whether the URL is rejected client-side before sending or by the server (seeerror_for_status()). Remediation: query fewer sites, or split the call manually.
- exception dataretrieval.exceptions.Unchunkable[source]
Bases:
RequestTooLargeNo chunking plan fits the URL byte limit.
Raised by the Water Data chunker when even the smallest reducible plan (every list axis at one atom per sub-request, the filter at one clause per sub-request) still exceeds the server’s byte limit – so unlike
URLTooLong, automatic splitting has already been tried and exhausted. Shrink the input lists, simplify the filter, or split the call manually.
- dataretrieval.exceptions.error_for_status(status: int, message: str, *, retry_after: float | None = None) DataRetrievalError[source]
Return the typed
DataRetrievalErrorfor an HTTP error status.The one status-to-type mapping every request path shares (the legacy
querypath,waterdata,nadp/streamstats), so a given status becomes the same type everywhere:413, 414 ->
URLTooLong(aRequestTooLarge) – the “too long” semantic is more actionable than a bare status, and it matches the client-side over-long-URL case429 ->
RateLimited5xx ->
ServiceUnavailableanything else ->
HTTPError
messageis used verbatim;retry_afteris attached only to the transient (TransientError) types. status must be an error status (>= 400) – classifying a success or redirect is a usage error and raisesValueError.