Current section

Files

Jump to
libero src libero@error.erl
Raw

src/libero@error.erl

-module(libero@error).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/libero/error.gleam").
-export_type([never/0, panic_info/0, rpc_error/1]).
-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.
?MODULEDOC(
" Error envelope for Libero RPC responses.\n"
"\n"
" Every RPC response is shaped as `Result(T, RpcError(E))`, where\n"
" `E` is the server function's app-specific error type. The wire\n"
" carries this envelope uniformly regardless of whether the server\n"
" function itself returns a bare `T` or an explicit `Result(T, E)`.\n"
"\n"
" ## Three categories of failure\n"
"\n"
" 1. App errors (`AppError(e)`) are expected, domain-specific\n"
" failure modes the server function chose to model, such as\n"
" `DuplicateEmail`, `NotFound`, or `ValidationFailed`. Handled\n"
" by the app's UI (show a form error, navigate away, and so on).\n"
"\n"
" 2. Framework errors (`MalformedRequest`, `UnknownFunction`) are\n"
" errors in the RPC layer itself. The request was garbage or\n"
" named a function that doesn't exist. Usually deployment skew\n"
" or a client-side bug.\n"
"\n"
" 3. Internal errors (`InternalError(trace_id, message)`) are\n"
" unexpected runtime panics caught by the dispatch layer. The\n"
" `trace_id` is opaque to the client; the full panic details\n"
" are logged server-side under that id. The `message` field\n"
" contains a client-safe string suitable for display to end\n"
" users without exposing internal details.\n"
"\n"
" ## Bare-T server functions\n"
"\n"
" Server functions that return a bare type (`List(Record)`, `Int`,\n"
" `Option(Note)`, and so on) are exposed to clients as\n"
" `Result(T, RpcError(Never))`, where `Never` is an uninhabited\n"
" type. Gleam's exhaustiveness checker understands that `Never`\n"
" can't be constructed, so the `AppError(_)` match arm is\n"
" statically unreachable and users don't need to write it.\n"
).
-type never() :: any().
-type panic_info() :: {panic_info, binary(), binary(), binary()}.
-type rpc_error(WPT) :: {app_error, WPT} |
malformed_request |
{unknown_function, binary()} |
{internal_error, binary(), binary()}.