Exception Hierarchy
siege_utilities follows a fail-loud-over-silent-swallow policy: when
a function cannot deliver its documented output, it raises a typed exception
rather than returning None, False, or an empty container that looks
like a legitimate “no result.” This distinguishes real failures from
expected empty-input paths and prevents silent data corruption in
downstream pipelines.
This page catalogs the typed exceptions across the library. Every exception
subclasses a standard Python exception (LookupError, ValueError,
RuntimeError) so broad existing handlers continue to work.
Design principles
Lookup failures are ``LookupError``. Missing chart types, missing client configs, and similar “you asked for X but X doesn’t exist” cases.
Parameter / input failures are ``ValueError``. Missing required parameters, invalid values, bad config shapes.
Operation failures are ``RuntimeError``. Failed I/O, failed parse, failed API call — anything where the inputs were valid but the work did not complete.
Not-found return values are preserved where semantic.
list_X()returning[], lookup helpers returningNonewhen the caller should handle absence as normal — these are unchanged. The rewrite only affects sites where absence was masking a transport or parse failure.Every raise chains with ``from e``. Inspect
exc.__cause__to see the underlying error (JSONDecodeError,OSError,HTTPError, etc.).
Reporting
Top-level config export / import
- exception siege_utilities.reporting.ReportingConfigError[source]
Bases:
RuntimeErrorRaised when a reporting configuration export / import cannot complete.
Chart type registry
- exception siege_utilities.reporting.chart_types.UnknownChartTypeError[source]
Bases:
LookupErrorRaised when a chart type name is not in the registry.
- exception siege_utilities.reporting.chart_types.ChartParameterError[source]
Bases:
ValueErrorRaised when required parameters are missing or invalid.
- exception siege_utilities.reporting.chart_types.ChartCreationError[source]
Bases:
RuntimeErrorRaised when the underlying create function fails to produce a Figure.
Client branding
- exception siege_utilities.reporting.client_branding.ClientBrandingNotFoundError[source]
Bases:
LookupErrorRaised when a named client’s branding configuration does not exist.
- exception siege_utilities.reporting.client_branding.ClientBrandingError[source]
Bases:
RuntimeErrorRaised when a client-branding operation fails unexpectedly.
Use the __cause__ attribute (set via raise … from e) to inspect the underlying error (YAMLError, OSError, ValidationError, etc.).
Geographic
Census Bureau geocoder
- exception siege_utilities.geo.census_geocoder.CensusGeocodeError[source]
Bases:
RuntimeErrorRaised when the Census geocoder API call fails unexpectedly.
Distinct from “no match” results (which return a CensusGeocodeResult with matched=False). This exception indicates an API / network / parse failure where the geocoder could not even attempt to match. Use __cause__ to inspect the underlying exception.
Before this change, geocode_single() and geocode_batch() caught all
failures (network, API, parse) and returned
CensusGeocodeResult(matched=False). Downstream pipelines treated
unmatched rows as “address not findable” and dropped them — so API
outages silently poisoned entire batches with fake unmatched rows.
CensusGeocodeError surfaces the real cause.
Spatial data sources
- exception siege_utilities.geo.spatial_data.SpatialDataError[source]
Bases:
RuntimeErrorRaised when a non-boundary spatial data fetch fails unexpectedly.
Used by GovernmentDataSource and OpenStreetMapDataSource, which load generic portal datasets and OSM Overpass results respectively. Boundary retrieval has its own exception hierarchy in boundary_result.py.
Use the
__cause__attribute (set viaraise ... from e) to inspect the underlying exception (HTTPError, JSONDecodeError, etc.).
Used by GovernmentDataSource (CKAN-style portals) and
OpenStreetMapDataSource (Overpass API). Distinct from boundary
retrieval, which has its own hierarchy below.
Boundary retrieval
- exception siege_utilities.geo.boundary_result.BoundaryRetrievalError[source]
Bases:
SiegeGeoErrorBase exception for all boundary retrieval failures.
Inherits from
SiegeGeoErrorso callers can catch the entire siege_utilities exception family with a singleexcept SiegeError:. Previously this stood alone outside the documented hierarchy and slipped pastexcept SiegeErrorblocks.
- exception siege_utilities.geo.boundary_result.BoundaryInputError[source]
Bases:
BoundaryRetrievalErrorInvalid input parameters (state FIPS, year, geographic level).
- exception siege_utilities.geo.boundary_result.BoundaryDiscoveryError[source]
Bases:
BoundaryRetrievalErrorFailed to discover available boundary types or construct a URL.
- exception siege_utilities.geo.boundary_result.BoundaryUrlValidationError[source]
Bases:
BoundaryRetrievalErrorConstructed URL is not accessible (HTTP error, timeout, etc.).
- exception siege_utilities.geo.boundary_result.BoundaryDownloadError[source]
Bases:
BoundaryRetrievalErrorDownload succeeded but the file is corrupt or not a valid zip.
- exception siege_utilities.geo.boundary_result.BoundaryParseError[source]
Bases:
BoundaryRetrievalErrorDownloaded data could not be parsed as a shapefile/GeoDataFrame.
- exception siege_utilities.geo.boundary_result.BoundaryConfigurationError[source]
Bases:
BoundaryRetrievalErrorBoundary type requires parameters that were not provided (e.g., state FIPS, congress number).
Migration guidance
Callers that relied on the pre-rewrite silent-swallow behavior must
migrate to try/except around the new exception types.
Before:
result = registry.create_chart("unknown_type")
if result is None:
log.warning("chart creation failed")
return None
After:
try:
result = registry.create_chart("unknown_type")
except UnknownChartTypeError:
log.warning("unknown chart type")
return None
except ChartCreationError as e:
log.error("chart creation failed: %s", e.__cause__)
raise
Because the exception types subclass standard Python exceptions, you can
also use a single broad except LookupError: / except ValueError: /
except RuntimeError: if you do not need to distinguish cases. The
__cause__ attribute still gives you the original error.
Further reading
../../docs/FAILURE_MODES — complete anti-pattern catalog
../../docs/ARCHITECTURE — three-layer dependency model