Exceptions and Errors
The :std/error
library provides base classes for exceptions and errors.
usage
(import :std/error)
The root of the hierarchy
The exception hierarchy is rooted in two base classes: Error
and Exception
.
- Instances of
Error
indicate error conditions, and they have a standard payload of a message, a subsystem or procedure name where the error originated, and a list of irritants.Error
mixes inStackTrace
which allows the system to fill stack traces -- seeraise
below. - Instances of
Exception
indicate exceptional conditions that are not necessarily errors, and do not have a standard payload.Exception
does not mixStackTrace
, as it is possible to useException
instances for control flow, in which case it would be inappropriate to include stack traces without the programmer's consent.
Exception
(defclass Exception ...)
The base class for naked exception objects; there are no fields or slots in this class.
Exception?
(Exception? obj)
Predicate for Exception
instances
RuntimeException
(defclass (RuntimeException Exception ...) ...)
Wrapper class for exceptions generated by the gambit runtime, such that a stack trace can be attached.
The original exception is available at the exception
slot.
RuntimeException?
(RuntimeException? obj)
Predicate for RuntimeException
instances.
StackTrace
(defclass StackTrace (continuation))
Mixin class for stack traces in errors.
If an exception class that mixes in StackTrace
is raised by this module's
redefined raise
(see below), then the current continuation will be
captured (if not already captured) and stored in the continuation
slot. The continuation backtrace will be displayed by
Error::display-exception
to facilitate debugging.
StackTrace?
StackTrace?
Predicate for StackTrace
mixins.
Error
(defclass (Error StackTrace ...) ...)
(Error message irritants: (irritants []) where: (where #f))
The base class for errors.
The constructor takes a required argument (message
) and two optional keyword arguments:
message
; this the error message to display to the user.irritants
; this is a list of objects related to the error condition.where
; this is usually a symbol (may be false) indicating the source of the error.
Error?
(Error? obj)
Predicate for Error
instances.
Error-message
(Error-message err) -> string
err := instance of Error
Accessor for the error message.
Error-irritants
(Error-irritants err) -> list
err := instance of Error
Accessor for the error irritants.
Error-where
(Error-where err) -> any
err := instance of Error
Accessor for the error origin.
Error:::init!
(Error:::init! err message irritants: (irritants []) where: (where #f))
err := instance of Error
The base Error
constructor, which error subclasses can call to
initialize the base error reprsentation.
Error::display-exception
(Error::display-exception err port)
err := instance of Error
port := output port
Base method for displaying Errors, including a stack trace if
available; see StackTrace
below.
Standard Error Classes
The following are predefined classes with standard semantics, used througout the standard library.
ContractViolation
(defclass (ContractViolation StackTrace Error) ())
Error indicating an input parameter contract violation condition.
ContractViolation?
(ContractViolation? exn)
Predicate testing whether the error is a contract violation condition.
contract-violation-error?
(def contract-violation-error! ContractViolation?)
Same as ContractViolation?
.
IOError
(defclass (IOError StackTrace Error) ())
Error indicating an IO condition.
IOError?
(IOError? exn)
Predicate testing whether the error is an IO condition.
io-error?
(def io-error? IOError?
same as IOError?
PrematureEndOfInput
(defclass (PrematureEndOfInput IOError) ())
Error indicating that input was exhausted prematurely; similar to EOF exceptions in other languages.
PrematureEndOfInput?
(PrematureEndOfInput? obj)
Predicate testing whether the error is a premature end of input condition.
premature-end-of-input-error?
(def permature-end-of-input? PrematureEndOfInput?)
Same as PrematureEndOfInput?
.
IOClosed
(deferror-class (IOClosed IOError))
Error indicating that the IO sink or source has been closed and thus no further IO operations can be performed.
IOClosed?
(IOClosed? obj)
Predicate testing whether the error is an IO closed condition.
io-closed-error?
(def io-closed-error? IOClosed?)
Same as IOClosed?
.
Timeout
(deferror-class Timeout)
Error indicating that some operation has timed out.
Timeout?
(Timeout? obj)
Predicate testing whether the error is a timeout.
timeout-error?
(def timeout-error? Timeout?)
Same as Timeout?
.
ContextError
(deferror-class ContextError)
Error indicating that some operation was performed out of context.
ContextError?
(ContextError? obj)
Predicate testing whether the error is a context error
context-error?
(def context-error? ContextError?)
Same as ContextError?
.
UnboundKey
(deferror-class UnboundKey)
Error indicating that some lookup operation failed because a key was unbound.
UnboundKey?
(UnboundKey? obj)
Predicate testing whether the condition is an unbound key error
unbound-key-error?
(def unbound-key-error? UnboundKey?)
Same as UnboundKey?
.
Raising exceptions
The library redefines raise
and error
so that it fills stack
traces where appropriate.
It also provides some utility procedure for raising particular errors
without caring about the particulars of the condition system.
error
(error message irritant ...)
Like basic Scheme's error
, but raises with stack trace.
raise
(raise exn)
Raises an exception condition.
If the exception object is an instance of StackTrace
, then unless
there is already a continuation because this is a re-raise, the
continuation is captured and stored in the continuation
slot.
check-argument
(check-argument expr expectation argument)
expr := a boolean expression
expectation := a string describing the expectation
argument := the argument being checked for reporting purposes.
Evaluates the boolean expression expr
and raises a contract violation if it is #f
.
raise-contract-violation
(raise-contract-violation where contract irritant ...)
Raises a ContractViolation
condition.
raise-io-error
(raise-io-error where message . irritants)
Raises an IOError
condition.
raise-premature-end-of-input
(raise-premature-end-of-input where . irritants)
p
Raises a PrematureEndOfInput
condition.
raise-io-closed
(raise-io-closed where message . irritants)
Raises an IOClosed
condition.
raise-timeout
(raise-timeout where message . irritants)
Raises a Timeout
condition.
raise-context-error
(raise-context-error where message . irritants)
Raise a ContextError
condition.
raise-key-error
(raise-key-error where message . irritants)
Raise a KeyError
condition.
BUGS
Sometimes something that really shouldn't happen, but it did; because, Murphy.
BUG
(BUG where message . irritants)
Raise a bug condition.
is-it-bug?
(is-it-bug? obj)
Checks whether an error condition was caused by a something unexpected, a bug.
Defining custom Error classes
The library offers a utility macro to define error classes that follow the standard library conventions. You don't have to use it, but if you are building a library it is recommended to do so.
deferror-class
(deferror-class Class slots predicate-alias [constructor = Error:::init!])
(deferror-class (Class Mixin ...) slots predicate-alias [constructor = Error:::init!])
The first form defines a class Class
with slots slots
that extends
Error
, mixing in StackTrace
. It also defines a predicate alias
for the class's instance predicate that can be exported to hide the
internal error details.
Dumping stack traces
It is useful to invoke a thunk and dump an exception stack trace if it
raises; this can be accomplished with the with-exception-stack-trace
and dump-stack-trace!
utility procedures.
This can be useful when you are dealing with exceptions that do not
mixin StackTrace
(which will automatically dump the stack trace when
displaying the exception with display-exception
).
with-exception-stack-trace
(with-exception-stack-trace thunk (error-port (current-error-port)))
Invokes thunk
with an exception handler that dumps the exception
stack trace with dump-stack-trace!
if (dump-stack-trace?)
is true (the default).
dump-stack-trace?
(define dump-stack-trace? (make-parameter #t))
A parameter that controls whether some a stack trace will be dumped when an exception is presented to the user.
This parameter is notably used by the display-exception
method for
the Error
type in the runtime, and by with-exception-stack-trace
(see above) that is also used in the default exception handler installed
in threads spawned with spawn-actor
.
It is also heeded by exit-with-error
(see below).
You can (dump-stack-trace? #f)
or locally (parameterize ((dump-stack-trace? #f)) ...)
to disable this stack trace dump,
in case you are building a program for end-users rather than for developers,
and want to control what limited error output they see.
Or you can re-enable them based on a debug flag at the CLI
in cases you want them to provide you with extra debugging information,
or log bug reports directly to your servers, etc.
dump-stack-trace!
(dump-stack-trace! cont exn (error-port (current-error-port)))
Displays the exception exn
, dumping the stack trace of continuation
cont
if there is no stack trace information in the exception itself.
exit-with-error
(exit-with-error exception) => [exit]
Display the exception
to current error port and exit with error code 2.
exit-on-error?
(def exit-on-error? (make-parameter #t))
This parameter controls whether call-with-exit-on-error
, with-exit-on-error
,
call-with-getopt
, and any function that indirectly uses them,
will exit if an error is caught, rather than pass on the error
and return to the REPL (or let a more fundamental function exit).
If dump-stack-trace?
is true, then the exception will be reprinted
a second time with dump-stack-trace?
bound to false, so that
the text of the exception should be printed a second time after the stack dump.
call-with-exit-on-error
(call-with-exit-on-error thunk)
Calls the thunk
in an environment wherein if an error is caught and
(exit-on-error)
is true, exit-with-error
will be called,
causing an error message to be printed and the process to exit with exit code 2.
If (exit-on-error)
is false, the error will simply be raised again.
This mechanism enables users to modify the parameter (e.g. via a flag passed at the Unix CLI or a change made at the Scheme REPL) and control whether to exit with an error (e.g. for end-users) or enter a debugger REPL (e.g. for developers).
with-exit-on-error
(with-exit-on-error body ...)
Evaluates the body
as in a thunk
passed to call-with-exit-on-error
.