9.2 Exceptions
See Exceptions for information on the Racket exception
model. It is based on a proposal by Friedman, Haynes, and Dybvig
[Friedman95].
Whenever a primitive error occurs in Racket, an exception is
raised. The value that is passed to the current exception
handler for a primitive error is always an instance of the
exn structure type. Every exn structure value has a
message field that is a string, the primitive error message.
The default exception handler recognizes exception values with the
exn? predicate and passes the error message to the current
error display handler (see error-display-handler).
Primitive procedures that accept a procedure argument with a
particular required arity (e.g., call-with-input-file,
call/cc) check the argument’s arity immediately, raising
exn:fail:contract if the arity is incorrect.
9.2.1 Raising Exceptions
Raises an exception, where
v represents the exception being
raised. The
v argument can be anything; it is passed to the
current
exception handler.
If barrier? is true, then the call to the exception
handler is protected by a continuation barrier, so that
multiple returns/escapes are impossible. All exceptions raised by
racket functions effectively use raise with a
#t value for barrier?.
Breaks are disabled from the time the exception is raised until the
exception handler obtains control, and the handler itself is
parameterize-breaked to disable breaks initially; see
Breaks for more information on breaks.
Raises the exception
exn:fail, which contains an error
string. The different forms produce the error string in different
ways:
(error sym) creates a message string by concatenating
"error: " with the string form of sym.
(error msg v ...) creates a message string by
concatenating msg with string versions of the vs
(as produced by the current error value conversion handler; see
error-value->string-handler). A space is inserted before
each v.
(error src frmat v ...) creates a
message string equivalent to the string created by
(format (string-append "~s: " frmat) src v ...)
In all cases, the constructed message string is passed to
make-exn:fail, and the resulting exception is raised.
Examples: |
> (error 'failed) | error: failed | > (error "failed" 23 'pizza (list 1 2 3)) | failed 23 pizza (1 2 3) | > (error 'method-a "failed because ~a" "no argument supplied") | method-a: failed because no argument supplied |
|
Creates an
exn:fail:contract value and
raises it as
an exception. The
name argument is used as the source
procedure’s name in the error message. The
expected argument
is used as a description of the expected type.
In the first form, v is the value received by the procedure
that does not have the expected type.
In the second form, the bad argument is indicated by an index
bad-pos (counting from 0), and all of the original
arguments v are provided (in order). The resulting error
message names the bad argument and also lists the other arguments. If
bad-pos is not less than the number of vs, the
exn:fail:contract exception is raised.
Examples: |
| > (feed-cow 'turkey) | feed-cow: expected argument of type <cow>; given 'turkey | > (define (feed-animals cow sheep goose cat) | (if (not (eq? goose 'goose)) | (raise-type-error 'feed-animals "goose" 2 cow sheep goose cat) | "fed the animals")) |
| > (feed-animals 'cow 'sheep 'dog 'cat) | feed-animals: expects type <goose> as 3rd argument, given: | 'dog; other arguments were: 'cow 'sheep 'cat |
|
Creates an
exn:fail:contract value and
raises it as
an exception. The
name is used as the source procedure’s
name in the error message. The
message is the error
message. The
v argument is the improper argument received by
the procedure. The printed form of
v is appended to
message (using the error value conversion handler; see
error-value->string-handler).
Additional arguments are concatenated to the error message like
message and v. Every other additional argument
(starting with the argument after v) must be a string, but a
string need not have a following value argument.
Creates an
exn:fail:contract:arity value and
raises
it as an exception. The
name is used for the source
procedure’s name in the error message.
The arity-v value must
be a possible result from procedure-arity, except
that it does not have to be normalized (see procedure-arity? for
the details of normalized arities); raise-arity-error
will normalize the arity and use the normalized form in the error message.
If name is a procedure, its actual arity is
ignored.
The arg-v arguments are the actual supplied
arguments, which are shown in the error message (using the error value
conversion handler; see error-value->string-handler); also,
the number of supplied arg-vs is explicitly mentioned in the
message.
Creates an
exn:fail:syntax value and
raises it as an
exception. Macros use this procedure to report syntax errors.
The name argument is usually #f when expr
is provided; it is described in more detail below. The
message is used as the main body of the error message.
The optional expr argument is the erroneous source syntax
object or S-expression (but the expression #f cannot be
represented by itself; it must be wrapped as a syntax
object). The optional sub-expr argument is a syntax object
or S-expression (again, #f cannot represent itself) within
expr that more precisely locates the error. Both may appear
in the generated error-message text if
error-print-source-location is #t. Source location
information in the error-message text is similarly extracted from
sub-expr or expr when at least one is a syntax
object and error-print-source-location is #t.
If sub-expr is provided and not #f, it is used (in
syntax form) for the exprs field of the generated exception
record, else the expr is used if provided and not
#f. In either case, the syntax object is consed onto
extra-sources to produce the exprs field, or
extra-sources is used directly for exprs if neither
expr nor sub-expr is provided and not #f.
The form name used in the generated error message is determined
through a combination of the name, expr, and
sub-expr arguments:
When name is #f, and when expr is
either an identifier or a syntax pair containing an identifier as
its first element, then the form name from the error message is the
identifier’s symbol.
When name is #f and when expr is not
an identifier or a syntax pair containing an identifier as its
first element, then the form name in the error message is
"?".
symbol: When name is a symbol, then the symbol
is used as the form name in the generated error message.
9.2.2 Handling Exceptions
Any procedure that takes one argument can be an exception handler. If
the exception handler returns a value when invoked by raise,
then raise propagates the value to the “previous” exception
handler (still in the dynamic extent of the call to raise,
and under the same barrier, if any). The previous exception handler is
the exception handler associated with the rest of the continuation
after the point where the called exception handler was associated with
the continuation; if no previous handler is available, the
uncaught-exception handler is used (see below). In all cases, a call
to an exception handler is parameterize-breaked to disable
breaks, and it is wrapped with call-with-exception-handler to
install the exception handler that reports both the original and
newly raised exceptions.
A
parameter that determines an exception handler used by
raise when the relevant continuation has no exception handler
installed with
call-with-exception-handler or
with-handlers. Unlike exception handlers installed with
call-with-exception-handler, the handler for uncaught
exceptions must not return a value when called by
raise; if
it returns, an exception is raised (to be handled by an exception
handler that reports both the original and newly raised exception).
The default uncaught-exception handler prints an error message using
the current error display handler (see error-display-handler)
and then escapes by calling the current error escape handler (see
error-escape-handler). The call to each handler is
parameterized to set error-display-handler to the
default error display handler, and it is parameterize-breaked
to disable breaks. The call to the error escape handler is further
parameterized to set error-escape-handler to the default
error escape handler; if the error escape handler returns, then
the default error escape handler is called.
When the current error display handler is the default handler, then the
error-display call is parameterized to install an emergency error
display handler that logs an error (see log-error) and never
fails.
Evaluates each pred-expr and handler-expr in the
order that they are specified, and then evaluates the bodys
with a new exception handler during its dynamic extent.
The new exception handler processes an exception only if one of the
pred-expr procedures returns a true value when applied to the
exception, otherwise the exception handler is invoked from the
continuation of the with-handlers expression (by raising the
exception again). If an exception is handled by one of the
handler-expr procedures, the result of the entire
with-handlers expression is the return value of the handler.
When an exception is raised during the evaluation of bodys,
each predicate procedure pred-expr is applied to the
exception value; if a predicate returns a true value, the
corresponding handler-expr procedure is invoked with the
exception as an argument. The predicates are tried in the order that
they are specified.
Before any predicate or handler procedure is invoked, the continuation
of the entire with-handlers expression is restored, but also
parameterize-breaked to disable breaks. Thus, breaks are
disabled by default during the predicate and handler procedures (see
Breaks), and the exception handler is the one from
the continuation of the with-handlers expression.
The exn:fail? procedure is useful as a handler predicate to
catch all error exceptions. Avoid using (lambda (x) #t) as a
predicate, because the exn:break exception typically should
not be caught (unless it will be re-raised to cooperatively
break). Beware, also, of catching and discarding exceptions, because
discarding an error message can make debugging unnecessarily
difficult.
Like
with-handlers, but if a
handler-expr procedure
is called, breaks are not explicitly disabled, and the handler call is
in tail position with respect to the
with-handlers* form.
9.2.3 Configuring Default Handling
The error escape handler is normally called directly by an exception
handler, in a parameterization that sets the error
display handler and error escape handler to the default
handlers, and it is normally parameterize-breaked to disable
breaks. To escape from a run-time error in a different context, use
raise or error.
Due to a continuation barrier around exception-handling calls,
an error escape handler cannot invoke a full continuation that was
created prior to the exception, but it can abort to a prompt (see
call-with-continuation-prompt) or invoke an escape
continuation (see call-with-escape-continuation).
A parameter for the
error display handler, which is called
by the default exception handler with an error message and the
exception value. More generally, the handler’s first argument is a
string to print as an error message, and the second is a value
representing a raised exception.
The default error display handler displays its first argument
to the current error port (determined by the
current-error-port parameter) and extracts a stack trace (see
continuation-mark-set->context) to display from the second
argument if it is an exn value but not an
exn:fail:user value.
The default error display handler in DrRacket also uses
the second argument to highlight source locations.
To report a run-time error, use raise or procedures like
error, instead of calling the error display handler
directly.
A parameter whose value is used as the maximum number of characters
used to print a Racket value that is embedded in a primitive error
message.
A parameter whose value is used by the default
error display handler
as the maximum number of lines of context (or “stack trace”) to
print; a single “...” line is printed if more lines are available
after the first
cnt lines. A
0 value for
cnt disables context printing entirely.
A parameter that determines the
error value conversion
handler, which is used to print a Racket value that is embedded in a
primitive error message.
The integer argument to the handler specifies the maximum number of
characters that should be used to represent the value in the resulting
string. The default error value conversion handler prints
the value into a string (using the current global port print
handler; see global-port-print-handler). If the printed form
is too long, the printed form is truncated and the last three
characters of the return string are set to “...”.
If the string returned by an error value conversion handler is longer
than requested, the string is destructively “truncated” by setting
the first extra position in the string to the null character. If a
non-string is returned, then the string "..." is used. If a
primitive error string needs to be generated before the handler has
returned, the default error value conversion handler is used.
Calls to an error value conversion handler are parameterized
to re-install the default error value conversion handler, and to
enable printing of unreadable values (see print-unreadable).
A parameter that controls whether read and syntax error messages
include source information, such as the source line and column or the
expression. This parameter also controls the error message when a
module-defined variable is accessed before its definition is executed;
the parameter determines whether the message includes a module
name. Only the message field of an
exn:fail:read,
exn:fail:syntax, or
exn:fail:contract:variable
structure is affected by the parameter. The default is
#t.
9.2.4 Built-in Exception Types
Raised for exceptions that represent errors, as opposed to
exn:break.
Raised for errors from the inappropriate run-time use of a function or
syntactic form.
Raised when a procedure is applied to the wrong number of arguments.
Raised for division by exact zero.
Raised by functions like
fx+ when the result would not be a fixnum.
Raised when a continuation is applied where the jump would cross a
continuation barrier.
Raised for a syntax error that is not a
read error. The
exprs indicate the relevant source expressions,
least-specific to most-specific.
Raised by
#%top or
set! for an
unbound identifier within a module.
Raised for a
read error. The
srclocs indicate the
relevant source expressions.
Raised for a
read error, specifically when the error is due
to an unexpected end-of-file.
Raised for a
read error, specifically when the error is due
to an unexpected non-character (i.e., “special”) element in the
input stream.
Raised for an error related to the filesystem (such as a file not
found).
Raised for an error when attempting to create a file that exists
already.
Raised for a version-mismatch error when loading an extension.
Raised for TCP and UDP errors.
Raised for an error due to insufficient memory, in cases where sufficient
memory is at least available for raising the exception.
Raised for an error due to an unsupported feature on the current
platform or configuration.
Raised for errors that are intended to be seen by end users. In
particular, the default error printer does not show the program
context when printing the error message.
Raised asynchronously (when enabled) in response to a break request.
The continuation field can be used by a handler to resume the
interrupted computation.
A property that identifies structure types that provide a list of
srcloc values. The property is normally attached to structure
types used to represent exception information.
The property value must be a procedure that accepts a single
value—the structure type instance from which to extract source
locations—and returns a list of srclocs. Some error
display handlers use only the first returned location.
As an example,
Returns the
srcloc-getting procedure associated with
v.
The fields of a
srcloc instance are as follows:
source — An arbitrary value identifying the source,
often a path (see Paths).
line — The line number (counts from 1) or
#f (unknown).
column — The column number (counts from 0) or
#f (unknown).
position — The starting position (counts from 1) or
#f (unknown).
span — The number of covered positions (counts from
0) or #f (unknown).