Skip to content

Error hierarchy

Every class ActiveSanction::Error covers, alphabetically. Organised for lookup by class name — an operator with an exception class in front of them, not a narrative to read start to finish. For the tree shape and what to do about retryable? in a request path, see Handle errors.

The class list, its parent, and which attributes it adds are generated from the class hierarchy itself — see site/bin/generate_errors.rb — so a subclass added under an existing parent appears here without an edit to this page. When it is raised and what retryable? resolves to are written by hand below, from reading the raising code.

source_id (which list, or nil), status (the HTTP status behind the failure, where there was one), and to_h (both of those plus the message and retryable?, as a Hash) — from the Error module every class here mixes in. Rows below list only what a class adds beyond these three.

InvalidArgument is also a Ruby ::ArgumentError, and MissingKey is also a ::KeyError — Ruby gives an exception one superclass, and both already had a standard-library class before this gem existed. rescue ActiveSanction::Error still catches both.

Snapshot::Bundle raises four errors, and they warrant four different responses:

ClassMeansResponse
Snapshot::Bundle::CorruptThe bytes are damaged: truncated, a digest or record-count mismatch, a bad magic lineObtain the bundle again
Snapshot::Bundle::UntrustedSignatureThe bytes are intact and signed by somebody other than the expected publisherDo not screen against it
Snapshot::Bundle::Unsigned(a subclass of the above) Verification was asked for and there is no signature at allDo not screen against it
Snapshot::Bundle::UnsupportedFormatWritten under a format version, schema, or encoding this reader does not implementUpgrade the gem

Corrupt and UntrustedSignature are deliberately different errors: “these bytes were damaged” and “these bytes came from somewhere else” are different incidents, and only one is fixed by downloading the file again.

ClassParentRetryableAttributes addedRaised when
ConfigurationErrorStandardErrorNever (false, unconditionally).—This installation is set up wrong: a blank user_agent, a negative timeout, a value a Configuration writer refuses.
FetchErrorSourceErrorFrom the HTTP status: 408, 425, 429, and 5xx are true; every other status is false.—The bytes could not be obtained. Raised directly by the fetch layer; HttpClient::Error and its subclasses cover net/http's own failures.
HttpClient::ConnectionErrorHttpClient::ErrorAlways true — a DNS failure, a refused or reset connection, a TLS failure.—The request never completed.
HttpClient::ErrorFetchErrorInherited from FetchError: from the HTTP status, false when there is none.—Base for every failure HttpClient raises where the server never produced a status to hand back. Not raised directly.
HttpClient::InvalidRedirectHttpClient::ErrorNever.—A Location that cannot be resolved, or that leaves HTTP entirely.
HttpClient::RedirectLoopHttpClient::ErrorNever.—A redirect chain that returns to a URL already visited.
HttpClient::ResponseErrorHttpClient::ErrorFrom the HTTP status carried on #response (inherited from FetchError).responseRaised by Response#success! for a status the caller declared fatal.
HttpClient::TimeoutErrorHttpClient::ErrorAlways true.—The connection or a read exceeded its timeout, and retries did not save it.
HttpClient::TooManyRedirectsHttpClient::ErrorNever.—The redirect chain exceeded max_redirects without reaching a body.
IntegrityErrorSourceErrorNever.—The bytes are not what they claim to be. Raised directly only where no more specific subclass below applies.
InvalidArgumentArgumentErrorNever.—A public method was called with something it cannot use.
Matcher::NotSyncedStorageErrorNever — retrying does not create a snapshot that never existed.—Nothing has ever been synced, so Matcher has nothing to screen against.
MissingKeyKeyErrorNever.—A field or column asked for by name that does not exist.
ParseErrorSourceErrorNever.line, locator, offset, recordThe bytes arrived and could not be read as the declared format.
Parsers::XmlRecords::MalformedDocumentParseErrorNever (inherited from ParseError).—Raised by an XML backend when the payload stops being well-formed XML.
PayloadCache::ChecksumMismatchPayloadCache::CorruptEntryNever.—A cached payload's bytes no longer hash to the checksum recorded beside them.
PayloadCache::CorruptEntryIntegrityErrorNever.—A cached payload cannot be trusted: the sidecar is unreadable, or its bytes do not match it.
PayloadCache::PayloadMissingStorageErrorNever.—Nothing is stored under that source and checksum, or its blob is gone.
QueryErrorInvalidArgumentNever.—A screening query that cannot be run: an empty sources: list, a threshold outside 0..100, a limit of zero.
Snapshot::Bundle::CorruptIntegrityErrorNever — the fix is obtaining the bundle again, not retrying the same bytes.—A bundle is not what it says it is. See the four bundle failures above.
Snapshot::Bundle::UnsignedSnapshot::Bundle::UntrustedSignatureNever.—Verification was asked for and the bundle carries no signature at all. See the four bundle failures above.
Snapshot::Bundle::UnsupportedFormatStorageErrorNever — the fix is upgrading the gem, not retrying.—Written under a format version, schema, or encoding this reader does not implement. See the four bundle failures above.
Snapshot::Bundle::UntrustedSignatureIntegrityErrorNever.—The bundle is intact and somebody other than the expected publisher signed it. See the four bundle failures above.
Snapshot::ChecksumMismatchIntegrityErrorNever.—A stored snapshot's content no longer hashes to the checksum stored beside it.
SourceErrorStandardErrorNever (the base's own default) — a subclass below almost always overrides this.—Something went wrong with one list. Raised directly only where the failure fits none of FetchError, ParseError, or IntegrityError.
Sources::DeclarationErrorConfigurationErrorNever.—An adapter does not declare what Sources::Base requires, or is asked for a declaration it never made.
Sources::DuplicateKeyConfigurationErrorNever.—Two adapters try to register under the same key.
Sources::MissingPayloadFetchErrorAlways true.—A source's file could not be obtained: the publisher confirmed a copy this process does not hold, and re-asking for it in full did not produce one either.
Sources::UnknownSourceConfigurationErrorNever.—A source key nothing is registered under is asked for.
Storage::CorruptSnapshotStorageErrorNever.—A stored snapshot's bytes cannot be read as one, or claim to be a different source than the one they are filed under.
Storage::MissingSnapshotStorageErrorNever.—A source has never been synced, or its snapshot has been deleted, asked for by name.
Storage::UnsupportedSchemaStorageErrorNever.—A stored snapshot was written under a schema version newer than this reader implements.
StorageErrorStandardErrorNever (the base's own default).—The store could not answer. Raised directly only where no more specific subclass applies.
Sync::FailedStandardErrortrue only when every source that failed in the run failed retryably.reportRaised by Sync::Report#success!, for a caller that wants any failure in a run to be fatal. Never raised by the run itself.
UnsupportedErrorStandardErrorNever.—This object cannot do that: a backend without the capability asked for, an abstract method a subclass never implemented.
ValidatorStore::CorruptStoreStorageErrorNever.—A validator store's backing bytes cannot be read as validators.