ffiec-data-connect (Python)
Exceptions
FFIECError and its subclasses — NoDataError, CredentialError, ValidationError, ConnectionError, RateLimitError, XMLParsingError, SessionError, SOAPDeprecationError.
Every library exception inherits from FFIECError. Catching that one class
captures everything the library can throw (except for standard Python
errors from argument parsing, which the library lets propagate).
FFIECError # base
├── NoDataError
├── CredentialError
├── ValidationError
├── ConnectionError
├── RateLimitError
├── XMLParsingError
├── SessionError
└── SOAPDeprecationError
Common structure
FFIECError.__init__(message, details=None) stores:
| Attribute | Type |
|---|---|
message | str |
details | dict[str, Any] |
__str__ renders as "{message} | Details: {details}" when details is
non-empty, else just message. Log either; both are safe to stringify.
Subclasses accept type-specific keyword arguments and populate details
themselves — documented below.
Legacy mode
If legacy error mode is enabled (default in v3.0.0 for v2 back-compat),
the library raises ValueError instead of these specific types. See
configuration for the toggles. New code should
call disable_legacy_mode() once at startup so it gets the typed
exceptions.
FFIECError
Base class. Usable for a catch-all except:
from ffiec_data_connect import FFIECError, collect_data
try:
df = collect_data(creds, reporting_period="12/31/2025", rssd_id="480228", series="call")
except FFIECError as e:
log.error("ffiec call failed: %s", e)
NoDataError
NoDataError(rssd_id: str | None = None, reporting_period: str | None = None)
Raised when the FFIEC returns a structurally-valid empty response. Common
causes: the institution didn’t file for that period; the RSSD is retired
before reporting_period; the quarter is in the future.
details contains whichever of rssd_id and reporting_period were
supplied.
CredentialError
CredentialError(message: str, credential_source: str | None = None)
Raised by
OAuth2Credentials on empty
username, empty bearer token, or malformed JWT shape. Also raised by
create_protocol_adapter when
given an unknown credential type. details["credential_source"] tags the
failure site (e.g. "oauth2_init").
ValidationError
ValidationError(field: str, value: Any, expected: str)
Raised for bad input to the collect_* functions — invalid output_type,
invalid date_output_format, invalid force_null_types, non-numeric
rssd_id, malformed reporting_period. details always contains:
{"field": ..., "provided_value": ..., "expected": ...}
Always indicates a caller bug. Fix the input; don’t retry.
ConnectionError
ConnectionError(message: str, url: str | None = None, status_code: int | None = None)
Transport-layer failures: DNS, TLS, connection refused, 5xx responses,
read timeouts. For 5xx specifically, the library retries internally via
httpx; this exception surfaces after retries are exhausted.
Note: this name shadows Python’s builtin ConnectionError. Import it
explicitly from the library if you need to distinguish:
from ffiec_data_connect import ConnectionError as FFIECConnectionError
RateLimitError
RateLimitError(retry_after: int | None = None)
Raised on HTTP 429 from the FFIEC. details["retry_after_seconds"] is
populated from the Retry-After header when present.
from ffiec_data_connect import RateLimitError
import time
try:
periods = collect_reporting_periods(creds)
except RateLimitError as e:
time.sleep(e.details.get("retry_after_seconds", 60))
periods = collect_reporting_periods(creds)
The built-in RateLimiter will normally
prevent this — see it as a safety net, not a control-flow tool. If you
see this in production, lower your rate-limit setting.
XMLParsingError
XMLParsingError(message: str, xml_snippet: str | None = None)
Raised when the XBRL processor can’t parse a facsimile response. Usually
indicates the FFIEC returned an error page with a 200 OK status, or the
XBRL schema changed. details["xml_snippet"] contains the first 200
characters of the offending document (truncated for safety).
SessionError
SessionError(message: str, session_state: str | None = None)
Historical — raised by the v2 SOAP connection handling. Still exported because some internal code paths reference it, but you should not encounter it against a REST-only install. If you do, file a bug.
SOAPDeprecationError
SOAPDeprecationError(
soap_method: str,
rest_equivalent: str,
code_example: str,
)
The one exception you’ll see most often if you’re porting v2 code. Raised by:
WebserviceCredentials.__init__FFIECConnection.__init__SOAPAdapter.__init__create_protocol_adapterwhen passedWebserviceCredentialscollect_*functions when the deprecated(session, creds, ...)form receives a non-Nonesession
The __str__ is a multi-line banner pointing at the REST equivalent and
the PWS login URL:
======================================================================
FFIEC SOAP API DISCONTINUED
======================================================================
...
REST API equivalent: OAuth2Credentials(username, bearer_token)
Example:
from ffiec_data_connect import OAuth2Credentials
creds = OAuth2Credentials(username="...", bearer_token="eyJ...")
...
Treat every occurrence as an immediate rewrite. See Migration from v2.
Exception-type quick reference
| Raised by | Exception |
|---|---|
| Bad user input (types, formats) | ValidationError |
| Missing / malformed token | CredentialError |
| FFIEC returned empty | NoDataError |
| 429 from server | RateLimitError |
| 5xx / network failure | ConnectionError |
| XBRL parse failure | XMLParsingError |
| SOAP symbol used | SOAPDeprecationError |
See also
- Configuration —
disable_legacy_mode()to opt into these types. - Troubleshooting — common error scenarios and their fixes.
- Upstream
exceptions.py.