Skip to content

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-After when the server sends one. That includes a download from the content CDN. A Retry-After over 30 seconds raises RateLimitError straight 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.

errors property #

errors: list[dict[str, Any]]

Raw error details from the problem document.

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.

errors property #

errors: list[dict[str, Any]]

Raw error details from the problem document.

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.

errors property #

errors: list[dict[str, Any]]

Raw error details from the problem document.

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.

errors property #

errors: list[dict[str, Any]]

Raw error details from the problem document.

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.

errors property #

errors: list[dict[str, Any]]

Raw error details from the problem document.

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.

errors property #

errors: list[dict[str, Any]]

Raw error details from the problem document.

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.

errors property #

errors: list[dict[str, Any]]

Raw error details from the problem document.

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.

errors property #

errors: list[dict[str, Any]]

Raw error details from the problem document.

item_errors property #

item_errors: tuple[ItemError, ...]

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).

errors property #

errors: list[dict[str, Any]]

Raw error details from the problem document.

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.

errors property #

errors: list[dict[str, Any]]

Raw error details from the problem document.

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.

errors property #

errors: list[dict[str, Any]]

Raw error details from the problem document.

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.

errors property #

errors: list[dict[str, Any]]

Raw error details from the problem document.

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.

errors property #

errors: list[dict[str, Any]]

Raw error details from the problem document.

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.

successful_outcomes property #

successful_outcomes: tuple[RegistrationOutcome, ...]

Return every outcome whose resource was committed.

Provisional, because each outcome is a generated API model.

failed_indices property #

failed_indices: tuple[int, ...]

Return item indices, preserving the server's -1 lineage sentinel.

bookshelf.InvalidBundleError #

InvalidBundleError(message: str, *, remedy: str = _REBUILD)

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 #

ItemError(status: int, detail: str)

One item a non-atomic batch request rejected.