Exceptions#

Every h5i-db failure raises a subclass of h5i_db.H5iError, and every instance carries the same structured envelope the CLI prints on stderr:

try:
    db.read("nope")
except h5i_db.NotFoundError as e:
    e.code        # "table_not_found"   (stable, branchable identifier)
    e.hint        # what to try next (e.g. how to list tables)
    e.retryable   # False               (retrying without a change won't help)

Messages are formatted "[{code}] {message} (hint: {hint})".

Hierarchy#

Everything subclasses H5iError, which subclasses Exception:

Exception Meaning Typical codes
H5iError Base class for all h5i-db errors (attributes: code, hint, retryable) closed, query
NotFoundError Database, table, version or snapshot does not exist database_not_found, table_not_found, version_not_found, snapshot_not_found
ConflictError Concurrent-writer conflict or already-exists collision; usually retryable version_conflict, table_exists, database_exists, lock_timeout
InvalidInputError Bad argument, schema mismatch, sort-order violation or unsupported operation invalid_input, schema_mismatch, sort_order_violation, unsupported
PolicyError Operation forbidden by the mutation policy or a read-only handle policy_violation, read_only
CorruptionError Checksum/format verification failed; data may be damaged or written by a newer h5i-db corruption, format_too_new
LimitError A configured limit (memory, max_rows, segment count) was exceeded limit_exceeded
TimeoutError The operation exceeded its deadline timeout
StorageError Underlying storage / IO / encoding failure storage, io, arrow, parquet, metadata

h5i_db.TimeoutError shadows the builtin

It subclasses H5iError, not Python's builtin TimeoutError, so catch h5i_db.TimeoutError (or H5iError) specifically.

Patterns#

Branch on type for control flow, on .code for precision:

try:
    db.append("trades", batch, expected_version=v)
except h5i_db.ConflictError:
    v = db.versions("trades")[-1]["version"]     # re-read, re-derive, retry
except h5i_db.InvalidInputError as e:
    if e.code == "sort_order_violation":
        batch = batch.sort_by("ts")              # fix and retry once
    else:
        raise

Respect retryable: it encodes whether backing off can help. ConflictError and TimeoutError generally can be retried; InvalidInputError and PolicyError cannot, so fix the call (or get the plan reviewed) instead.

Surface hint: hints are written to be shown to a user, a log, or an LLM agent deciding its next step. Don't swallow them.

Catch-all: except h5i_db.H5iError catches every h5i-db failure while letting genuine bugs (TypeError, …) propagate. A closed handle raises H5iError with code == "closed".