rebol document

Appendix 2 - Errors

REBOL/Core Users Guide
Main Table of Contents
Send Us Feedback

Contents:

1. Overview
2. Error Categories
2.1 Syntax Errors
2.2 Script Errors
2.3 Math Errors
2.4 Access Errors
2.5 User Errors
2.6 Internal Errors
3. Catching Errors
4. Error Object
5. Generating Errors
6. Error Messages
6.1 Syntax Errors
6.2 Script Errors
6.3 Access Errors
6.4 Internal Errors

1. Overview

Errors are exceptions that occur when certain irregular conditions occur. These conditions range from syntax errors to file or network access errors. Here are a few examples:

12-30
** Syntax Error: Invalid date -- 12-30.
** Where: (line 1) 12-30
1 / 0
** Math Error: Attempt to divide by zero.
** Where: 1 / 0
read %nofile.r
** Access Error: Cannot open /example/nofile.r.
** Where: read %nofile.r

Errors are processed within the system as values of the error! datatype. An error is an object that, if evaluated, will print an error message and halt. You can also catch errors and handle them in your script. Errors can be passed to functions, returned from functions, and assigned to variables.

2. Error Categories

There are several categories of errors.

2.1 Syntax Errors

Syntax errors occur when a script uses REBOL syntax incorrectly. For instance, if a closing bracket is missing or a string is missing its closing quote, a syntax error will occur. These errors only occur during the load or evaluation of a file or string.

2.2 Script Errors

Script errors are general run-time errors. For instance, an invalid argument to a function will cause a script error.

2.3 Math Errors

Math errors occur when a math operation cannot be processed. For instance, when attempting to divide by zero an error will occur.

2.4 Access Errors

Access errors occur when a problem occurs with a file, port or network access. For example, an access error will occur when attempting to read a file that does not exist.

2.5 User Errors

User errors are generated explicitly by a script by creating an error value and returning it.

2.6 Internal Errors

Internal errors occur within the REBOL interpreter.

3. Catching Errors

You can catch errors with the try function. The try function is similar to the do function. It evaluates a block, but always returns a value, even when an error occurs.

When no error occurs, try returns the value of a block. For example:

print try [100 / 10]
10

When an error occurs, try returns the error. If you write:

print try [100 / 0]
** Math Error: Attempt to divide by zero.
** Where: 100 / 0

the error is returned from the try and the print function cannot handle it.

To handle errors in a script, you must prevent REBOL from evaluating the error. You can prevent an error from being evaluated by passing it to a function. For instance, the error? function will return true when it is passed an error:

print error? try [100 / 0]
true

You can also print the data type of the value returned from a try:

print type? try [100 / 0]
error!

The disarm function converts an error to an error object that can be examined. In the example below, the error variable holds an error object:

error: disarm try [100 / 0]

When an error is disarmed, it will be an object! data type, not an error! datatype. Evaluating the disarmed object will not cause an error:

probe disarm try [100 / 0]
make object! [
    code: 400
    type: 'math
    id: 'zero-divide
    arg1: none
    arg2: none
    arg3: none
    near: [100 / 0]
    where: none
]

Error values can be set to a word before they are disarmed. To set a word to an error, it must be preceded by a function that prevents the error from propagating further. For example:

disarm err: try [100 / 0]

Setting a variable enables you to access the value of the block later. The example below will print an error or non-error value:

either error? result: try [100 / 0] [
    probe disarm result
][
    print result
]

4. Error Object

The error object shown above has the structure:

make object! [
    code: 400
    type: 'math
    id: 'zero-divide
    arg1: none
    arg2: none
    arg3: none
    near: [100 / 0]
    where: none
]

Where the fields are:

 codeThe error code number. These are obsolete and should not be used.
 typeThe type field identifies the error category. It is always a word data type of syntax, script, math, access, user, and internal.
 idThe id field is the name for the error as a word. It identifies the specific error that occurred within the error category.
 arg1This field holds the first argument to the error message. For instance, it may include the data type of the value that caused the error.
 arg2This field holds the second argument to the error message.
 arg3This field holds the third argument to the error message.
 nearThe near field is a code fragment that shows where the error occurred.
 whereThe where field is reserved.

You can write code that checks any of the error object fields. In this example, the error is printed only when the error id indicates a divide by zero error:

error: disarm try [1 / 0]
if error/id = 'zero-divide [
    print {It is a Divide by Zero error}
]
It is a Divide by Zero error

The error id word also provides the error block that will be printed by the interpreter. For example:

error: disarm try [print zap]
probe get error/id
[:arg1 "has no value"]

This block is defined by the system/errors object.

5. Generating Errors

User errors can be generated. The simplest way to generate an error is make it. Here is an example:

make error! "this is an error"
** User Error: this is an error.
** Where: make error! "this is an error"

Any of the existing errors can be generated by making the error with a block argument. This block contains the error category name and the error message id name. If the error requires arguments, the arguments follow the message id name. The arguments are what define the arg1, arg2 and arg3 values in the error object. Here is an example:

make error! [script expect-set series! number!]
** Script Error: Expected one of: series! - not: number!.
** Where: make error! [script expect-set series! number!]

Custom errors can be entered into the system/error object's user category. This is done by making a new user category with new entries. These entries are used when generating errors. For instance, the following example enters an error into the user category:

system/error/user: make system/error/user [
    my-error: "a simple error"
]

Now an error can be generated using the my-error message id:

if error? err: try [
    make error! [user my-error]
] [probe disarm err]
make object! [
    code: 803
    type: 'user
    id: 'my-error
    arg1: none
    arg2: none
    arg3: none
    near: [make error! [user my-error]]
    where: none
]

To create more informative errors, define an error that uses data available when it is generated. This data is included in the disarmed error object and printed as part of the error message. For instance, to use all three argument spaces in an error object:

system/error/user: make system/error/user [
    my-error: [:arg1 "doesn't go into" :arg2 "using" :arg3]
]

if error? err: try [
    make error! [user my-error [this] "that" my-function]
] [probe disarm err]
make object! [
    code: 803
    type: 'user
    id: 'my-error
    arg1: [this]
    arg2: "that"
    arg3: 'my-function
    near: [make error! [user my-error [this] "that" my-function]]
    where: none
]

The error message generated for my-error can be printed without stopping the script:

disarmed: disarm err
print bind (get disarmed/id) (in disarmed 'id)
this doesn't go into that using my-function

A new library category may be created if there is a need to group a series of errors together by making a new category in system/error:

system/error: make system/error [
    my-errors: make object! [
        code: 1000
        type: "My Error Category"
        error1: "a simple error"
        error2: [:arg1 "doesn't go into" :arg2 "using" :arg3]
    ]
]

The type defined in the error object will be the error type printed when the error is generated. The following example illustrates generating an error from both error1 and error2 in the my-error category.

Generating an error from error1. This error requires no arguments:

disarmed: disarm try [make error! [my-errors error1]]
print get disarmed/id
a simple error

Generating an error from error2 requires three arguments:

disarmed: disarm try [
make error! [my-errors error2 [this] "that" my-function]]
print bind (get disarmed/id) (in disarmed 'id)
this doesn't go into that using my-function

Finally, the description that returns the errors defined in my-errors may be obtained with:

probe get in get disarmed/type 'type
My Error Category

6. Error Messages

Listed below is a list of all errors defined in the system/error object error catalog.

6.1 Syntax Errors

6.1.1 invalid

Data could not be translated into a valid REBOL datatype. In other words, a malformed value was evaluated.

Message:

["Invalid" :arg1 "--" :arg2]

Example:

filter-error try [load "1024AD"]
** Syntax Error: Invalid integer -- 1024AD
** Where: (line 1) 1024AD

6.1.2 missing

A block, string or paren expression was left unclosed.

Message:

["Missing" :arg2 "at" :arg1]

Example:

filter-error try [load "("]
** Syntax Error: Missing ) at end-of-script
** Where: (line 1) (

6.1.3 header

An attempt was made to evaluate a file as a REBOL script and the file did not have a REBOL header.

Message:

Script is missing a REBOL header

Example:

write %no-header.r {print "data"}
filter-error try [do %no-header.r]
** Syntax Error: Script is missing a REBOL header
** Where: do %no-header.r

6.2 Script Errors

6.2.1 no-value

An attempt was made to evaluate an undefined word.

Message:

[:arg1 "has no value"]

Example:

filter-error try [undefined-word]
** Script Error: undefined-word has no value
** Where: undefined-word

6.2.2 need-value

An attempt was made to define a word to nothing. A set-word was used without an argument.

Message:

[:arg1 "needs a value"]

Example:

filter-error try [set-to-nothing:]
** Script Error: set-to-nothing needs a value
** Where: set-to-nothing:

6.2.3 no-arg

A function was evaluated without providing it with all the arguments it was expecting.

Message:

[:arg1 "is missing its" :arg2 "argument"]

Example:

f: func [b][probe b]
filter-error try [f]
** Script Error: f is missing its b argument
** Where: f

6.2.4 expect-arg

A function was provided an argument of a datatype it wasn't expecting.

Message:

[:arg1 "expected" :arg2 "argument of type:" :arg3]

Example:

f: func [b [block!]][probe b]
filter-error try [f "string"]
** Script Error: f expected b argument of type: block
** Where: f "string"

6.2.5 expect-set

Two series values were used together in a way that was not compatible. For instance, when trying to do a union between a string and a block.

Message:

["Expected one of:" :arg1 "- not:" :arg2]

Example:

filter-error try [union [a b c] "a b c"]
** Script Error: Expected one of: block! - not: string!
** Where: union [a b c] "a b c"

6.2.6 invalid-arg

This is a generic error for handling values that were used improperly. For instance, when a set-word is used inside of a function's specification block.

Message:

["Invalid argument:" :arg1]

Example:

filter-error try [f: func [word:][probe word]]
** Script Error: Invalid argument: word
** Where: func [word:] [probe word]

6.2.7 invalid-op

An attempt was made to use an operator that had been redefined. The operator used is no longer a valid operator.

Message:

["Invalid operator:" :arg1]

Example:

*: "operator redefined to a string"
filter-error try [5 * 10]
** Script Error: Invalid operator: *
** Where: 5 * 10

6.2.8 no-op-arg

A math or comparison operator was used without providing the second argument.

Message:

Operator is missing an argument

Example:

filter-error try [1 +]
** Script Error: Operator is missing an argument
** Where: 1 +

6.2.9 no-return

A function expecting a block to return a value did not return anything. For instance, when using the while or until function.

Message:

Block did not return a value

Examples:

filter-error try [ ; first block returns nothing
    while [print 10][probe "ten"]
]
10
** Script Error: Block did not return a value
** Where: while [print 10] [probe "ten"]
filter-error try [
    until [print 10] ; block returns nothing
]
10
** Script Error: Block did not return a value
** Where: until [print 10]

6.2.10 not-defined

A word used was not defined within any context.

Message:

[:arg1 "is not defined in this context"]

6.2.11 no-refine

An attempt was made to use a function refinement that didn't exist for that function.

Message:

[:arg1 "has no refinement called" :arg2]

Example:

f: func [/a] [if a [print "a"]]
filter-error try [f/b]
** Script Error: f has no refinement called b
** Where: f/b

6.2.12 invalid-path

An attempt was made to access a block or object value using a path that did not exist within that block or object.

Message:

["Invalid path value:" :arg1]

Example:

blk: [a "a" b "b"]
filter-error try [print blk/c]
** Script Error: Invalid path value: c
** Where: print blk/c
obj: make object! [a: "a" b: "b"]
filter-error try [print obj/d]
** Script Error: Invalid path value: d
** Where: print obj/d

6.2.13 cannot-use

An attempt was made to perform an operation on a value of an incompatible datatype. For instance, when attempting to add a string to a number.

Message:

["Cannot use" :arg1 "on" :arg2 "value"]

Example:

filter-error try [1 + "1"]
** Script Error: Cannot use add on string! value
** Where: 1 + "1"

6.2.14 already-used

An attempt was made to alias a word that had already been aliased.

Message:

["Alias word is already in use:" :arg1]

Example:

alias 'print "prink"
filter-error try [alias 'probe "prink"]
** Script Error: Alias word is already in use: prink
** Where: alias 'probe "prink"

6.2.15 out-of-range

An attempt was made to modify an invalid series index.

Message:

["Value out of range:" :arg1]

Example:

blk: [1 2 3]
filter-error try [poke blk 5 "five"]
** Script Error: Value out of range: 5
** Where: poke blk 5 "five"

6.2.16 past-end

An attempt was made to access series data beyond the length of the series.

Message:

Out of range or past end

Example:

blk: [1 2 3]
filter-error try [print fourth blk]
** Script Error: Out of range or past end
** Where: print fourth blk

6.2.17 no-memory

The system ran out of memory while trying to complete an operation.

Message:

Not enough memory

6.2.18 wrong-denom

A math operation was performed on money values of two different denominations. For instance, when trying to add USD$1.00 to DEN$1.50.

Message:

[:arg1 "not same denomination as" :arg2]

Example:

filter-error try [US$1.50 + DM$1.50]
** Script Error: US$1.50 not same denomination as DM$1.50
** Where: US$1.50 + DM$1.50

6.2.19 bad-press

An attempt was made to decompress a binary value that was corrupt or not a compressed format.

Message:

["Invalid compressed data - problem:" :arg1]

Example:

compressed: compress {some data}
change compressed "1"
filter-error try [decompress compressed]
** Script Error: Invalid compressed data - problem: -3
** Where: decompress compressed

6.2.20 bad-port-action

An attempt was made to perform an unsupported action on a port. For instance, when trying to use find on a TCP port.

Message:

["Cannot use" :arg1 "on this type port"]

6.2.21 needs

An attempt was made to run a script that needed either a new version of REBOL or a file that couldn't be found. This information will be found in the script's REBOL header.

Message:

["Script needs:" :arg1]

6.2.22 locked-word

An attempt was made to modify a protected word. The word will have been protected with the protect function.

Message:

["Word" :arg1 "is protected, cannot modify"]

Example:

my-word: "data"
protect 'my-word
filter-error try [my-word: "new data"]
** Script Error: Word my-word is protected, cannot modify
** Where: my-word: "new data"

6.2.23 dup-vars

A function was evaluated that had multiple occurrences of a word defined in its specification block. For instance, if the word arg was defined as both argument one and two.

Message:

["Duplicate function value:" :arg1]

Example:

filter-error try [f: func [a /local a][print a]]
** Script Error: Duplicate function value: a
** Where: func [a /local a] [print a]

6.3 Access Errors

6.3.1 cannot-open

A file could not be accessed. This could be a local or network file. Most common reason for this error is a nonexistent directory.

Message:

["Cannot open" :arg1]

Example:

filter-error try [read %/c/path-not-here]
** Access Error: Cannot open /c/path-not-here
** Where: read %/c/path-not-here

6.3.2 not-open

An attempt was made to use a port that was closed.

Message:

["Port" :arg1 "not open"]

Example:

p: open %file.txt
close p
filter-error try [copy p]
** Access Error: Port file.txt not open
** Where: copy p

6.3.3 already-open

An attempt was made to open a port that was already open.

Message:

["Port" :arg1 "already open"]

Example:

p: open %file.txt
filter-error try [open p]
** Access Error: Port file.txt already open
** Where: open p

6.3.4 already-closed

An attempt was made to close a port that had already been closed.

Message:

["Port" :arg1 "already closed"]

Example:

p: open %file.txt
close p
filter-error try [close p]
** Access Error: Port file.txt not open
** Where: close p

6.3.5 invalid-spec

An attempt was made to create a port with make using a specification that a port could not be built from.

Message:

["Invalid port spec:" :arg1]

Example:

filter-error try [p: make port! [scheme: 'naughta]]
** Access Error: Invalid port spec: scheme naughta
** Where: p: make port! [scheme: 'naughta]

6.3.6 socket-open

The operating system ran out of sockets to allocate.

Message:

["Error opening socket" :arg1]

6.3.7 no-connect

A connection to another host failed. This is generic error covering a range of reasons for the connection failure. When more information is known about the reason for the connection failure, a more specific error will be thrown.

Message:

["Cannot connect to" :arg1]

Example:

filter-error try [read http://www.host.dom/]
** Access Error: Cannot connect to www.host.dom
** Where: read http://www.host.dom/

6.3.8 no-delete

An attempt was made to delete a file that was either locked or protected.

Message:

["Cannot delete" :arg1]

Example:

p: open %file.txt
filter-error try [delete %file.txt]
** Access Error: Cannot delete file.txt
** Where: delete %file.txt

6.3.9 no-rename

An attempt was made to rename a file that was either locked or protected.

Message:

["Cannot rename" :arg1]

Example:

p: open %file.txt
filter-error try [rename %file.txt %new-name.txt]
** Access Error: Cannot rename file.txt
** Where: rename %file.txt %new-name.txt

6.3.10 no-make-dir

An attempt was made to create a directory in a file path that did not exist or was write protected.

Message:

["Cannot make directory" :arg1]

Example:

filter-error try [make-dir %/c/no-path/dir]
** Access Error: Cannot make directory /c/no-path/dir/
** Where: m-dir path return path

6.3.11 timeout

The timeout period elapsed while waiting to for a response from another host. This timeout is set in the port's timeout attribute.

Message:

Network timeout

6.3.12 new-level

An attempt was made within a script to change the security to a lower level of security that was denied. This is to say, whenever a script requests a lower security setting and the user denies the request, this error is thrown.

Message:

["Attempt to change security level to" :arg1]

Example:

secure quit
filter-error try [secure none] ; denied request

secure none

6.3.13 security

A security violation occurred. This will happen when an attempt is made to access a file or the network when the secure setting is set to throw.

Message:

REBOL - Security Violation

Example:

secure throw
filter-error try [open %file.txt]
** Access Error: REBOL - Security Violation
** Where: open %file.txt
secure none

6.3.14 invalid-path

A malformed file path was used.

Message:

["Bad file path:" :arg1]

Example:

filter-error try [read %/]

6.4 Internal Errors

6.4.1 bad-path

A path was evaluated that began with an invalid word.

Message:

["Bad path:" arg1]

Example:

path: make path! [1 2 3]
filter-error try [path]
** Internal Error: Bad path: 1
** Where: path

6.4.2 not-here

An attempt was made to use a REBOL/Command or REBOL/View feature from REBOL/Core.

Message:

[arg1 "not supported on your system"]

6.4.3 stack-overflow

The system's memory stack overflowed while trying to perform an operation.

Message:

["Stack overflow"]

Example:

call-self: func [][call-self]
filter-error try [call-self]
** Internal Error: Stack overflow
** Where: call-self

6.4.4 globals-full

The maximum allowable number of defined global words has been exceeded.

Message:

["No more global variable space"]

Updated 8-Apr-2005 - Copyright REBOL Technologies - Formatted with MakeDoc2
REBOL.com Documents Manual Dictionary Library Feedback