Arangox.Error exception (Arangox v0.8.0)

Copy Markdown View Source

The one error struct arangox produces.

Every Arangox.Client callback that fails returns one of these, and every error Arangox hands back is one of these. There is no second error shape.

Fields

  • :reason - an atom for pattern matching. Either a code from Arangox.Errno (:arango_document_not_found, :arango_conflict, ...) when the server supplied an errorNum, or a transport reason (:econnrefused, :closed, ...) when the failure happened below HTTP. nil only when neither is known. See Arangox.Client for which reasons mean the socket is gone. Two of them are arangox's own: :timeout, a request that ran out of time on the socket — which retires the connection, since arangox cannot tell where the abandoned response ended — and :deadline_exceeded, a request that was never sent because the caller's budget was already spent queueing for a connection, which leaves the connection healthy and checked in.
  • :status - the HTTP status, when the server responded.
  • :error_num - the raw ArangoDB errorNum, when the body supplied one. Always present together with :status, and preserved even when the number is absent from the vendored table and :reason is therefore :unknown.
  • :endpoint - the endpoint the failure happened against, with any userinfo stripped. See Arangox.Endpoint.redact/1.
  • :message - the human-readable message.

Branch on :reason, not on :message

:message is usually the server's own message, verbatim. ArangoDB controls its wording and changes it between releases, and it may contain values from the request. It is for humans and logs. :reason (and :status and :error_num) is the machine-readable surface:

case Arangox.get(conn, path) do
  {:error, %Arangox.Error{reason: :arango_document_not_found}} -> :gone
  {:error, %Arangox.Error{reason: :arango_conflict}} -> retry()
end

Because the message is server-controlled it is length-bounded when rendered: Exception.message/1 truncates at message_limit/0 bytes, so a pathological body cannot flood a log line. The :message field itself is untouched.

Nothing here carries credentials

Redaction is unconditional and has no opt-out: no message, no struct inspection and no log line arangox produces contains authentication material. The endpoint is redacted where it is stored, not only where it is rendered, so Exception.message/1, inspect/1 and the failed to connect line DBConnection logs are all covered by the same fix.

Summary

Functions

The maximum number of bytes of :message that message/1 renders.

Types

t()

@type t() :: %Arangox.Error{
  __exception__: term(),
  endpoint: Arangox.endpoint() | nil,
  error_num: non_neg_integer() | nil,
  message: binary(),
  reason: Arangox.Errno.t() | atom() | nil,
  status: pos_integer() | nil
}

Functions

message_limit()

@spec message_limit() :: pos_integer()

The maximum number of bytes of :message that message/1 renders.