The single exception type raised (or returned) by every TypeDB operation.
Errors carry a :kind describing where the failure came from:
:server— TypeDB answered with a structured error body.:codeholds the TypeDB error code (e.g."TSV11","AUT3","HSR4"),:statusthe HTTP status, and:messagethe server's message, including its cause trace.:transport— the request never produced an HTTP response (connection refused, DNS failure, TLS failure, socket closed).:timeout— the request exceeded the configured timeout.:unauthenticated— credentials were rejected, or the token expired and could not be renewed.:decode— the response body was not valid JSON, or did not match the shape this driver expects.:encode— the mirror of:decode: an Elixir term could not be turned into a TypeDB wire value. Agiven_rowsentry of a type TypeDB has no equivalent for, or aTypeDB.Durationwith a negative component, which TypeQL's grammar cannot express. Raised rather than returned, because it happens while the request is still being built and there is nothing to fail.:config— the driver was configured incorrectly. Raised at start-up.
Matching on TypeDB error codes
case TypeDB.query(conn, "social", "match $x isa nonexistent;") do
{:error, %TypeDB.Error{kind: :server, code: code}} -> {:bad_query, code}
{:ok, answer} -> answer
endError codes are stable across TypeDB releases and are the recommended thing to branch on; messages are not.
Summary
Functions
Builds an error from a TypeDB error response body.
Builds an error.
Whether retrying the call that produced this error could plausibly help.
The response statuses the driver treats as retryable by default.
Types
Functions
@spec from_response(pos_integer(), term()) :: t()
Builds an error from a TypeDB error response body.
TypeDB error bodies are %{"code" => code, "message" => message}. Anything
else is reported verbatim so that no information is lost.
Builds an error.
Public because TypeDB.HTTP is a public extension point and TypeDB.HTTP.request/6
is required to return one of these. Application code should be matching on
errors, not constructing them.
TypeDB.Error.new(:transport, "connection refused", reason: :econnrefused)Options
:code— TypeDB's own error code, for:servererrors:status— the HTTP status:reason— the underlying term, whatever it was:body— the response body that could not be understood
Whether retrying the call that produced this error could plausibly help.
case TypeDB.transaction(conn, "social", :write, &steps/1) do
{:error, %TypeDB.Error{} = error} ->
if TypeDB.Error.retryable?(error), do: retry_the_whole_thing(), else: give_up(error)
result ->
result
endNote what this is not for. By the time you are holding an error the driver
has already retried whatever its configuration allowed, so a true here does
not mean it gave up early. This is for the layer above — retrying a whole
transaction, requeueing a job — where the unit of work is bigger than one HTTP
call and the driver could not have retried it for you.
:server errors are judged by retryable_statuses/0 rather than by a
connection's :retry_on_status, because an error does not carry the
connection that produced it.
iex> TypeDB.Error.retryable?(TypeDB.Error.new(:transport, "connection refused"))
true
iex> TypeDB.Error.retryable?(TypeDB.Error.new(:server, "no such database", status: 404))
false
iex> TypeDB.Error.retryable?(TypeDB.Error.new(:unauthenticated, "bad password"))
false
@spec retryable_statuses() :: [pos_integer()]
The response statuses the driver treats as retryable by default.
429 is a server shedding load; 502, 503 and 504 are what a proxy, an
ingress or a load balancer answers while TypeDB restarts. All four say "not
now" rather than "no". This is the default of :retry_on_status.