THROW and Custom Errors
THROW lets you raise your own errors with custom messages and codes. Combined with SETERR trapping, this gives you structured error propagation through the call stack -- methods can signal failures, and callers can handle them.
THROW Syntax
throw "message", code
The error code must be in the developer range: 256--1024. Codes 0--255 are reserved for BBj system errors.
seterr handler
throw "Something went wrong", 300
release
handler:
print "Error #", err, ": ", errmes(-1)
release
Output:
Error # 300 : Something went wrong
THROW from Class Methods
THROW is most useful inside class methods for validation and error signaling. When a method throws and has no local SETERR, the error propagates up to the caller:
class public Validator
method public void validate(BBjString input$)
if len(input$) = 0 then
throw "Input cannot be empty", 256
fi
if len(input$) > 100 then
throw "Input too long (max 100 characters)", 257
fi
methodend
classend
seterr handler
declare Validator v!
v! = new Validator()
v!.validate("")
release
handler:
print "Validation error #", err, ": ", errmes(-1)
release
Output:
Validation error # 256 : Input cannot be empty
This is the standard pattern for defensive programming in BBj: classes validate their inputs with THROW, and calling code sets up SETERR or ERR= to handle failures.
Custom Error Messages with ERRMES
You can pre-register custom error messages for your error codes using ERRMES() as a statement:
errmes(256, "Validation: empty input")
errmes(257, "Validation: input too long")
rem Now errmes(256) returns your custom message
print errmes(256)
This is useful when you want consistent error messages across your application. Once registered, errmes(code) returns your custom message instead of the default.
RETRY
RETRY re-executes the statement that caused the error. This is useful for interactive prompts and transient-failure recovery:
seterr askAgain
print "Enter a number:"
input n$
x = num(n$)
print "You entered: ", x
release
askAgain:
seterr askAgain; rem Re-establish trap (SETERR resets after branching)
print "That was not a valid number. Please enter a number:"
retry
Key behavior: RETRY also restores the saved SETERR value from before the error occurred. However, since SETERR resets on branch, re-establishing it explicitly (as shown above) is the safer pattern.
Error Propagation Through the Call Stack
When THROW is called inside a method:
- BBj checks if the method has its own
SETERRhandler - If not, the error propagates to the caller
- The caller's
SETERRorERR=handles it - If no handler exists anywhere in the call chain, the program terminates with an error
This propagation is automatic -- you do not need to re-throw errors. A THROW in a deeply nested method will bubble up through the call stack until it reaches a handler.
class public Service
method public void process()
declare Validator v!
v! = new Validator()
v!.validate(""); rem Throws error 256 -- propagates to caller of process()
methodend
classend
See Reading Legacy Code for !THROWERROR STBL patterns and other pre-THROW error handling mechanisms.
- Custom Objects Tutorial: Error Handling -- THROW patterns in class-based code
- ERRMES() Function -- Full reference for error message functions
- STBL Formats -- THROWERROR and ERROR_HANDLER system table entries