Errors#
Every error the SDK raises for a failed operation subclasses BookshelfError. Each class below is importable from bookshelf, and is part of the semver promise, so catching it keeps working across minor releases. That covers PartialRegistrationError and the publisher errors too, even though the producer API and bookshelf.publisher that raise them are provisional. An attribute that returns a generated model or a producer type is provisional, such as PartialRegistrationError.successful_outcomes.
Misusing the API raises Python's own TypeError or ValueError instead, for example passing an argument a resource type does not accept. These signal a bug in the calling code rather than a condition to handle.
A success response whose JSON does not match the operation's schema raises ContractError. It means the platform and this SDK disagree about the contract, so upgrading bookshelf is the first thing to try.
Not found#
A volume, version, book, entry or resource that does not exist raises NotFoundError, whether the platform answered 404 or the SDK settled the lookup locally. NotFoundError is also a LookupError.
Looking up an entry a book does not index raises EntryNotFoundError. It is also a KeyError, so book["name"] behaves like any other mapping. Looking up a version a volume has not published raises VersionNotFoundError, which is also a KeyError, so volume["version"] behaves the same way.
Filtering or ordering on a column the data does not have raises SelectionError, which is also a KeyError. So does a filter value the column cannot be read as, and a selection the platform refuses.
HTTP responses#
An HTTP error response raises an APIError subclass chosen by status, so a caller can catch NotFoundError or ConflictError rather than compare status_code.
A 429 raises RateLimitError, with the wait the server asked for in retry_after. An HTML or other non-JSON error page comes from the CDN or proxy in front of the API rather than the API itself. Its 4xx raises GatewayError and its 5xx raises ServerError. The message names the status and the URL, never the page. A success whose body is not JSON at all also raises GatewayError. That is usually the web app's page answering a base URL with the wrong path.
APIError.problem holds the parsed problem document as a Problem, when the API sent one. A 409 from a batch that committed some items carries the rejected ones on ConflictError.item_errors.
A malformed BOOKSHELF_URL or base_url raises ConfigurationError. So does one carrying a query string, a fragment, a user@ part or a trailing /v1. A cache directory blocked by a file raises CacheDirectoryError, which is also an OSError.
Retries#
The client retries a request a few times before it raises, backing off with jitter between attempts.
- A 429 is retried for any method, waiting out
Retry-Afterwhen the server sends one. That includes a download from the content CDN. ARetry-Afterover 30 seconds raisesRateLimitErrorstraight away. - A 502, 503 or 504 is retried for idempotent methods only, so a write is never committed twice.
- A data read (
/data, timeseries, facets, preview and schema) is never retried after a 5xx or a timeout. The read that failed may be the one that took the server down, so a replay would only repeat it. - A 500 is never retried, because it is the API failing on this request.
- A refused connection is retried for any method, because nothing reached the server. A connect timeout is not, since the host did not answer within 10 seconds.
- A read timeout is never retried, since the attempt already waited the whole
timeout. A dropped connection on a metadata read is still retried.
Reference#
bookshelf.BookshelfError #
Bases: Exception
Base exception for all Bookshelf SDK errors.
bookshelf.APIError #
APIError(detail: str, *, status_code: int, problem: Problem | None = None, request_method: str | None = None, request_url: str | None = None)
Bases: BookshelfError
An HTTP error response from the API.
Attributes:
| Name | Type | Description |
|---|---|---|
status_code | int | HTTP status code returned by the server. |
detail | str | Human-readable detail string. |
problem | Problem | None | The parsed RFC 9457 problem document, when one was returned. |
request_method | str | None | HTTP method of the failing request, when known. |
request_url | str | None | URL or path of the failing request, when known. |
bookshelf.RequestValidationError #
RequestValidationError(detail: str, *, status_code: int, problem: Problem | None = None, request_method: str | None = None, request_url: str | None = None)
Bases: APIError
Raised on HTTP 400 / 422 request-validation failures.
bookshelf.AuthenticationError #
AuthenticationError(detail: str, *, status_code: int, problem: Problem | None = None, request_method: str | None = None, request_url: str | None = None)
Bases: APIError
Raised on HTTP 401 responses.
bookshelf.ForbiddenError #
ForbiddenError(detail: str, *, status_code: int, problem: Problem | None = None, request_method: str | None = None, request_url: str | None = None)
Bases: APIError
Raised on HTTP 403 responses.
bookshelf.NotFoundError #
NotFoundError(detail: str, *, status_code: int, problem: Problem | None = None, request_method: str | None = None, request_url: str | None = None)
Bases: APIError, LookupError
The named volume, version, book, entry or resource does not exist.
Raised on HTTP 404 responses, and with status_code 404 when a lookup the SDK settles locally finds nothing.
bookshelf.EntryNotFoundError #
EntryNotFoundError(detail: str, *, status_code: int, problem: Problem | None = None, request_method: str | None = None, request_url: str | None = None)
Bases: NotFoundError, _UnquotedKeyError
A book indexes no entry by the requested name.
bookshelf.VersionNotFoundError #
VersionNotFoundError(detail: str, *, status_code: int, problem: Problem | None = None, request_method: str | None = None, request_url: str | None = None)
Bases: NotFoundError, _UnquotedKeyError
A volume has published no book under the requested version.
bookshelf.ConflictError #
ConflictError(detail: str, *, status_code: int, problem: Problem | None = None, request_method: str | None = None, request_url: str | None = None)
Bases: APIError
Raised on HTTP 409 responses.
item_errors property #
The items a non-atomic batch rejected, when the conflict came from one.
Entries that are not shaped like an item failure are left out. The raw documents stay available on :attr:errors.
bookshelf.ServerError #
ServerError(detail: str, *, status_code: int, problem: Problem | None = None, request_method: str | None = None, request_url: str | None = None)
Bases: APIError
Raised on HTTP 5xx responses (after transient retries).
bookshelf.RateLimitError #
RateLimitError(detail: str, *, status_code: int = RATE_LIMITED, retry_after: float | None = None, problem: Problem | None = None, request_method: str | None = None, request_url: str | None = None)
Bases: APIError
Raised on HTTP 429 responses (after waiting out the retries the server allowed).
Attributes:
| Name | Type | Description |
|---|---|---|
retry_after | float | None | Seconds the server asked the client to wait, when it said. |
bookshelf.GatewayError #
GatewayError(detail: str, *, status_code: int, problem: Problem | None = None, request_method: str | None = None, request_url: str | None = None)
Bases: APIError
A response the API would not send, from a proxy, CDN or web app in front of it.
That is a non-JSON 4xx, or a success whose body is not the JSON the operation returns, such as the web app's HTML page answering a base URL with the wrong path. The API itself never answered, so the status says nothing about whether the data exists.
bookshelf.UnexpectedResponseError #
UnexpectedResponseError(detail: str, *, status_code: int, problem: Problem | None = None, request_method: str | None = None, request_url: str | None = None)
Bases: APIError
Raised when the server answers with a status the contract does not declare.
bookshelf.ContractError #
ContractError(detail: str, *, status_code: int, problem: Problem | None = None, request_method: str | None = None, request_url: str | None = None)
Bases: APIError
The API answered with JSON that is not shaped like the operation's response.
The server and this SDK disagree about the contract, usually because one of them is out of date. Upgrading bookshelf is the first thing to try.
bookshelf.TransportError #
Bases: BookshelfError
A network-level failure with no HTTP response (after transient retries).
bookshelf.AuthenticationRequiredError #
Bases: BookshelfError
No credential the API accepts is available, and none can be obtained here.
bookshelf.AuthConfigurationError #
Bases: BookshelfError
Ambient credential configuration is inconsistent or incomplete.
bookshelf.ConfigurationError #
Bases: BookshelfError
A setting such as the API URL is malformed.
bookshelf.CacheDirectoryError #
Bases: BookshelfError, OSError
The cache directory cannot be created or written, such as when a file is in the way.
bookshelf.ActionsTokenError #
Bases: AuthConfigurationError
The Actions runtime did not hand over an OIDC token.
bookshelf.OAuthError #
Bases: BookshelfError
Error during an OAuth authentication flow.
Covers the flow itself rather than one HTTP response, so it carries no status code and no OAuth error code.
bookshelf.SelectionError #
Bases: BookshelfError, _UnquotedKeyError
A selection names a column the data does not have, or a value a column cannot hold.
bookshelf.HashMismatchError #
Bases: BookshelfError
Downloaded bytes do not match the resource's declared SHA256.
bookshelf.UnsupportedConversionError #
Bases: BookshelfError
A converter does not apply to the resource type.
bookshelf.DataFrameSupportError #
Bases: BookshelfError
Raised when a conversion needs an optional package that is not installed.
bookshelf.PartialRegistrationError #
PartialRegistrationError(*, successful: Sequence[RegistrationSuccess], failures: Sequence[RegistrationFailure])
Bases: BookshelfError
A non-atomic batch committed some items and rejected others.
bookshelf.InvalidBundleError #
Bases: BookshelfError, ValueError
A bundle on disk breaks the contract a bundle promises.
The message names the invariant that failed and carries the detail a caller needs to render it. remedy is the sentence that tells the producer how to fix it. A caller therefore either holds a bundle that keeps its contract or holds an error explaining why it does not.
bookshelf.InvalidRecipeError #
Bases: BookshelfError, ValueError
A recipe on disk breaks a rule the recipe format promises.
bookshelf.InvalidReferenceError #
Bases: BookshelfError, ValueError
A bookshelf:// reference is not one this client can parse.
bookshelf.RecordingError #
Bases: BookshelfError, ValueError
A build asked the recorder for something a bundle cannot hold.
bookshelf.RecordRefusedError #
Bases: BookshelfError, ValueError
The recorder refused what it was asked to do before running the build.
bookshelf.Problem dataclass #
Problem(type: str, title: str, status: int, detail: str, instance: str | None, errors: tuple[Mapping[str, Any], ...])
The RFC 9457 problem document an API error response carried.
bookshelf.ItemError dataclass #
One item a non-atomic batch request rejected.