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
Errorindicate 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.Errormixes inStackTracewhich allows the system to fill stack traces -- seeraisebelow. - Instances of
Exceptionindicate exceptional conditions that are not necessarily errors, and do not have a standard payload.Exceptiondoes not mixStackTrace, as it is possible to useExceptioninstances 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.