Page
Library
Module
Module type
Parameter
Class
Class type
Source
Err
SourceErr is an abstraction to report located errors and warnings to the user.
The canonical syntax for an error produced by this lib is:
File "my-file", line 42, character 6-11:
42 | Hello World
^^^^^
Error: Some message that gives a general explanation of the issue.
Followed by more details.
It is heavily inspired by dune's user_messages and uses dune's error message rendering under the hood.
A value of type t
is an immutable piece of information that the programmer intends to report to the user, in a way that breaks flow. To give some concrete examples:
The exception that is raised to break the control flow of programs using Err
.
Examples:
When reporting an error:
if had_error then Err.raise [ Pp.text "An error occurred." ]
When requesting an exit code:
if shall_exit_42 then Err.exit 42
The standard usage for this library is to wrap entire sections in a protect
, which takes care of catching E
and handling it accordingly. You may also catch this exception manually if you need, for more advanced uses (in which case you'll take care of recording and re-raising backtraces, etc).
Return a Sexp
to inspect what inside t
. Note the sexp is not meant for supporting any kind of round trip serialization (there is no t_of_sexp
). Rather, this is for interoperability with other error handling mechanisms based on sexps. We think exposing this can help accommodating some use cases, making it easier to write expect tests involving Err
, etc.
Note that the exit code contained in t
is not shown by sexp_of_t
. See With_exit_code.sexp_of_t
if needed.
This part allows breaking the control flow with an exception indicating a request to end the program with a given exit code.
Request the termination of the program with the provided exit code. Make sure you have documented that particular exit code in the man page of your CLI. We recommend to stick to the error codes exposed by Exit_code
, which are documented by default and pervasively used by existing CLIs built with cmdliner. Raises E
.
val raise :
?loc:Loc.t ->
?hints:Pp_tty.t list ->
?exit_code:Exit_code.t ->
Pp_tty.t list ->
_
Raise a user error. You may override exit_code
with the requested exit code to end the program with. It defaults to Exit_code.some_error
.
Example:
let unknown_var var =
Err.raise
~loc
[ Pp.textf "Unknown variable '%s'" var ]
~hints:(Err.did_you_mean var ~candidates:[ "foo"; "bar"; "baz" ])
;;
val create :
?loc:Loc.t ->
?context:Pp_tty.t list ->
?hints:Pp_tty.t list ->
?exit_code:Exit_code.t ->
Pp_tty.t list ->
t
Create a err and return it, instead of raising it right away.
sexp s
is the preferred way to embed some context of type Sexp.t
into a _ Pp.t
paragraph as part of a error.
exn e
is the preferred way to embed an exception into a _ Pp.t
paragraph as part of an error.
add_context t items
prepends the supplied items to the context of t
. This approach reflects the idea of a stack: new context items are added to the front, representing the most recent layer of context.
When rendered in the console, context items are displayed before the main error paragraphs, with the most recently added context item appearing first. This mirrors the reverse navigation of the program's call stack, as context is typically added at the point where an error is caught and additional information is provided.
This mechanism is useful for incrementally building a high-level "stack trace" of user-defined context, helping to clarify the sequence of events leading to the error. See also reraise_with_context
.
Reraise with added context. See also add_context
. Usage:
match do_x (Y.to_x y) with
| exception Err.E e ->
let bt = Printexc.get_raw_backtrace () in
Err.reraise_with_context e bt [ Pp.text "Trying to do x with y"; Y.pp y ]
Helper to raise a user error from a result type.
ok_exn (Ok x)
is x
ok_exn (Error msg)
is Stdlib.raise (E msg)
Build an error from an exception. This retrieves e
if the exception is Err.E e
, otherwise this creates a new error using the sexp of the supplied exception.
Produces a "Did you mean ...?" hint
Set by the For_test.wrap
when wrapping sections for tests, accessed by libraries if needed.
This return the number of errors that have been emitted via Err.error
since the last reset_counts
(in practice that is the start of the program). Beware, note that errors raised as exceptions via functions such as Err.raise
do not affect the error count. The motivation is to allow exceptions to be caught without impacting the overall exit code.
A convenient wrapper for Err.error_count () > 0
.
This is useful if you are trying not to stop at the first error encountered, but still want to stop the execution at a specific breakpoint after some numbers of errors. To be used in places where you want to stop the flow at a given point rather than returning meaningless data.
Return the number of warnings that have been emitted via Err.warning
since the last reset_counts
.
Inspired by the git diff --color=<WHEN>
command line parameter, this library allows to access the rendering mode that should be used to style the output aimed for the user, in the terminal or perhaps using a pager.
If you use Log_cli.set_config
, your cli will also support the same --color
flag as git diff
. You can access the value that was set via the color_mode
getter. The default mode is `Auto
.
Even though it is traditionally called "color"-mode, this goes beyond simply colors and controls all forms of style rendering construct, such as bold, italic, and other ansi special characters.
Inspired by logging conventions in many CLI tools, this library provides a mechanism to control the verbosity of log messages based on their severity level. This allows users to filter messages, ensuring that only relevant information is displayed during program execution.
The log level can be set programmatically or via command-line flags using Log_cli
. The default log level is Warning
, meaning only warnings and errors will be displayed unless a more verbose level is explicitly set.
The available log levels are:
Quiet
: Suppresses all log messages, including errors.Error
: Displays only error messages.Warning
: Displays warnings and errors (default).Info
: Displays informational messages, warnings, and errors.Debug
: Displays all messages, including debug information.Programs can query the current log level using log_level
and check whether a specific level is enabled using log_enables
. This is useful for conditionally executing code that should only run at certain verbosity levels.
Example usage:
if Err.log_enables ~level:Debug
then (
(* Perform expensive debugging operations *)
let debug_data = compute_debug_data () in
Err.debug (lazy [ Pp.textf "Debug data: %s" debug_data ]))
Note: Functions such as Err.info
, Err.warning
, and Err.debug
automatically check the log level before emitting messages. You do not need to call log_enables
before using them.
When using Log_cli
, the log level can be set via a command-line flag (e.g., --verbosity=debug
). This ensures consistent behavior across applications using this library.
Note: A log level named App
has been added to ensure compatibility with the Logs
library, as this constructor is part of Logs.level
. However, this module does not differentiate between the Quiet
and App
levels. The App
level is primarily included to facilitate interoperability with third-party libraries that rely on Logs
.
A level for individual messages (by contrast to the current level of the log).
Access the current log level.
Tell whether the current log level enables the output of messages of the supplied level.
Print to stderr
(not thread safe). By default, prerr
will start by writing a blank line on stderr
if Err
messages have already been emitted during the lifetime of the program. That is a reasonable default to ensure that err messages are always nicely separated by an empty line, to make them more readable. However, if you structure your output manually, perhaps you do not want this. If reset_separator=true
, this behavior is turned off, and the first message of this batch will be printed directly without a leading blank line.
to_string_hum t
is shorthand to Sexp.to_string_hum (sexp_of_t t)
. This may be used if you want to embed t
as a string. Note you'll lose all colors and other style formatting. For pretty printing of errors to the console, see prerr
.
This part of the library allows the production of messages that do not raise.
For example: - Emitting multiple errors before terminating - Non fatal Warnings - Debug and Info messages
Errors and warnings are going to affect error_count
(and resp. warning_count
), which is going to be used by protect
to impact the exit code of the application. Use with care.
Emit an error on stderr if the log level is Error
or more (enabled by default). Note that this function increments the error count regardless of the log level (even when the message is not displayed that is).
Emit a warning on stderr if the log level is Warning
or more (enabled by default). Note that this function increments the warning count regardless of the log level (even when the message is not displayed that is).
Emit a information message on stderr. Requires a log level of Info
or more, disabled by default.
The last argument to debug
is lazy in order to avoid the allocation when debug messages are disabled. This isn't done with the other functions, because we don't expect other logging functions to be used in a way that impacts the program's performance, and using lazy causes added programming friction.
Emit a message from an existing error.
Rather than building a new Err.t
, this part of the API allows you to emit a message from a previously created err value. For example, you may catch an error raised by some code, and make that a warning instead.
let warn_on_error ~f =
try f () with
| Err.E e -> Err.emit e ~level:Warning
;;
The emit functions does check the current log level, and only emit the message if permitted it - for example, emit t ~level:Warning
actually emits a warning only when log_enables ~level:Warning = true
.
Emitting with level Error
(resp. Warning
) increments the global error count (resp. warning count), even when the log level is such that the message is not actually printed (such as in Quiet
mode, for example).
To be used by command line handlers, as well as tests.
protect f
will take care of running f
, and catch any user error. If the exit code must be affected it is returned as an Error
. This also takes care of catching uncaught exceptions and printing them to the screen. You may provide exn_handler
to match on custom exceptions and turn them into Err
for display and exit code. Any uncaught exception will be reported as an internal errors with a backtrace. When Err.am_running_test ()
is true the backtrace is redacted to avoid making expect test traces too brittle. protect
starts by performing a reset of the error and warning counts with a call to reset_counts
.
Private
is used by Log_cli
. We mean both libraries to work as companion libs. Note any of this can change without notice and without requiring a semver bump, so use at your own risk (or don't).
This part of the API is, or will be soon, deprecated. We have added ocamlmig
annotations to help with migrating existing code.
val create_s :
?loc:Loc.t ->
?hints:Pp_tty.t list ->
?exit_code:Exit_code.t ->
string ->
Sexplib0.Sexp.t ->
t
This is deprecated - use Err.create
instead.
val raise_s :
?loc:Loc.t ->
?hints:Pp_tty.t list ->
?exit_code:Exit_code.t ->
string ->
Sexplib0.Sexp.t ->
_
This is deprecated - use Err.raise
instead.
val reraise_s :
Printexc.raw_backtrace ->
t ->
?loc:Loc.t ->
?hints:Pp_tty.t list ->
?exit_code:Exit_code.t ->
string ->
Sexplib0.Sexp.t ->
_
This is deprecated - use Err.reraise_with_context
instead.
This was renamed Err.sexp
.