Q(uick)BASIC Statement: ON ERROR

Quick View

ON ERROR

An error-trapping statement that enables error handling and specifies the first line of the error-handling routine

Worth knowing

Useful and cross-version information about the programming environments of QBasic and QuickBasic.

Syntax
  • ON ERROR {GOTO line | RESUME NEXT}
Description/Parameter(s)
GOTO line Branches to the first line of the error-handling routine, specified by a label or line number. To disable error handling, specify GOTO 0.
RESUME NEXT Resumes execution with the statement following the statement that caused the run-time error. Use the ERR function to obtain the error code for the error.

If ON ERROR isn't used, any run-time error ends your program.

Example

The ERRDEV function programming example illustrates the use of ERDEV, ERDEV$, ERL, ERR, ERROR, ON ERROR, and RESUME.

Syntax
  • ON ERROR GOTO line
Description/Parameter(s)

The line argument is the line number or line label of the first line in the error-handling routine. This line must appear in module-level code.

If line cannot be found in the module where the error occurred, or if there is no ON ERROR GOTO statement, a backward search is made through the modules that invoked the module with the error. If an active error handler is found, it is used. If no active error handler is found, an error message is printed and program execution halts. The specific error message depends on the type of error.

Only modules in the invocation path are searched. Modules outside the path are not searched, even if there is no active error handler in the search path.

A line number of 0 disables error handling. It does not specify line 0 as the start of the error-handling code, even if the program contains a line numbered 0. Subsequent errors print an error message and halt the program. Once error handling is enabled, any error that can be trapped causes a jump to the specified error-handling routine.

Inside an error handler, executing an ON ERROR statement with a line number of 0 halts program execution and prints the error message for the error that caused the trap. This is a convenient way to halt a program in response to errors that cannot be processed by the error- handling routine.

Note that an error-handling routine is not a SUB or FUNCTION procedure or a DEF FN function. An error-handling routine is a module block of code marked by a line label or line number.

SUB and FUNCTION procedures and DEF FN functions can contain their own error handlers. The error handler must be located after the last executable statement but before the END SUB, END FUNCTION, or END DEF statement. To keep the error handler from executing when there is no error, the procedure or function must terminate with an EXIT SUB, EXIT FUNCTION, or EXIT DEF statement immediately ahead of the error handler, as in the following example:

  • SUB InitializeMatrix (var1, var2, var3, var4)
  • ON ERR GOTO ErrorHandler
  • EXIT SUB
  •  
  • ErrorHandler:
  • RETURN
  •  
  • END SUB
Note: Errors occurring within an error-handling routine are not trapped. These errors halt program execution after printing an error message.
Example

The following program gets a file name from the user and displays the file on the screen. If the file cannot be opened, an error-handling routine traps the error and starts the program again at the prompt for the file name.

DEFINT A-Z ' establish the error-handling routine ON ERROR GOTO ErrorHandler CLS ' get a file name INPUT "Enter the file to display: ",filename$ ' open the file OPEN filename$ FOR INPUT AS #1 ' display the file on the screen DO WHILE NOT EOF(1) LINE INPUT #1, aline$ PRINT aline$ LOOP END ' ' error handling routine handles only "Bad File Name"; ' aborts on any other error ' CONST BADFILENAME = 53 ErrorHandler: IF ERR = BADFILENAME THEN ' get another file name PRINT "File " UCASE$(filename$) " not found." INPUT "Enter the file to display: ",filename$ RESUME ELSE ' some other error, so print message and abort PRINT "Unrecoverable error--"; ERR ON ERROR GOTO 0 END IF
Syntax
  • ON [LOCAL] ERROR {GOTO line | RESUME NEXT | GOTO 0}
Description/Parameter(s)
  • LOCAL is a keyword that indicates an error-handling routine that is "local" to the procedure within which the error handler routine is located. A local error-handling routine:
    • Overrides any enabled module-level error-handling routines.
    • Is enabled only while the procedure within which it is located is executing.
  • Notice that the local error handler remains enabled while any procedures execute that are directly or indirectly called by the procedure within which the error handler is located. One of those procedures may supersede the local error handler.

  • Note: The module-level error-handling routines provided by previous versions of BASIC may be all you need; you may never need to use the LOCAL keyword.

  • The argument line is either in the module-level code or in the same procedure (if the LOCAL keyword is used). If not found in either place, BASIC generates a "Label Not Defined" compile-time error.
  • Use of the RESUME NEXT option causes program execution to resume with the statement immediately following the statement that caused the run-time error. This enables you to:
    • Continue execution of a block of program code despite a run-time error, then check for the cause of the error; or
    • Build the error-handling code in line with the main program or procedure, rather than at a remote location in the program.
  • The statement form ON ERROR GOTO 0 disables error handling. It does not specify line 0 as the start of the error-handling code, even if the program or procedure contains a line numbered 0.

General Usage Notes

  • If no ON ERROR statement is used in a program, any run-time error will be fatal. (BASIC generates an error message and program execution stops.)
  • Notice that an error-handling routine is not a SUB or FUNCTION procedure nor a DEF FNfunction. An error-handling routine is a block of code marked by a line label or line number.
  • An error-handling routine will not be executed unless it is enabled by execution of an
    • ON ERROR GOTO line
    statement (or unless a fault in the structure of the program causes program control to branch to or fall into the error-handling code). Once an error handler is enabled, if a run-time error that can be trapped occurs, then program control jumps to the enabled error- handling routine and the error handler becomes "active".
  • An error handler is active from the time a run-time error has been trapped until a RESUME statement is executed in the handler.
  • Error-handling routines must rely on the value in ERR to determine the cause of the error. The error-handling routine should test or save this value before any other error can occur or before calling a procedure that could cause an error. The value in ERR reflects only the last error to occur.
  • If you use the BC command line to compile a program that has been developed in the QBX environment and which has error-handling routines, compile with the /E or /X option. The QBX environment Make EXE command uses these options.
  • If an error occurs in a procedure or module that does not have an enabled error-handling routine, BASIC searches for an enabled, inactive error handler to trap the error. BASIC will search back through all the procedures and modules that have called the procedure where the error occurred.

Using Module-Level Error Handlers

  • Once enabled by execution of an
    • ON ERROR GOTO line
    statement, a module-level error handler stays enabled unless explicitly disabled by execution of an
    • ON ERROR GOTO 0
    statement somewhere in the module.
  • In a multiple-module program that contains only module-level error handlers, if an enabled and inactive error handler cannot be found in the module where the error occurred, BASIC will search back through the module-level code of all the calling modules, looking for an enabled, inactive error handler.
  • If an error occurs in a module-level error handler itself, BASIC does not automatically treat it as a fatal error. BASIC will search back through the module-level code of all the calling modules, looking for an enabled, inactive error handler.
  • If an ON ERROR GOTO 0 statement is encountered while the current module's module-level error handler is active, program execution is not automatically halted. BASIC will search back through the module-level code of all the calling modules, looking for an enabled, inactive error handler.

Procedure-Level Error Handlers

  • SUB and FUNCTION procedures and DEF FNfunctions can contain their own error-handling routines.
  • To enable a local error handler, use the statement
    • ON ERROR GOTO line
    The argument line must be a label or line number in the same procedure as the ON LOCAL ERROR GOTO statement.
  • The local error handler is automatically disabled when the procedure returns, or by execution of the statement
    • ON ERROR GOTO 0
  • You will want program flow to avoid the statements that make up the error-handling routine. One way to keep the error-handling code from executing when there is no error is to place an EXIT SUB, EXIT FUNCTION, or EXIT DEF statement immediately ahead of the error- handling routine, as in the following example:
    • SUB InitializeMatrix (var1, var2, var3, var4)
    • ON LOCAL ERROR GOTO ErrorHandler
    • EXIT SUB
    • ErrorHandler:
    • RESUME NEXT
    • END SUB
    The example shows the error-handling routine located after the EXIT SUB statement, and before the END SUB statement. This partitions the error-handling code from the normal execution flow of the procedure. However, error-handling code can be placed anywhere in a procedure.
  • In the QBX environment, or if the command-line compiler is used with the /O option:
    • If a local error handler is active and an END SUB, END FUNCTION, or END DEF statement is encountered, BASIC generates the run-time error message "No RESUME."
    • If an EXIT SUB, EXIT FUNCTION, or EXIT DEF statement is encountered, BASIC does not generates a run-time error; in other words, it is assumed that this does not represent a logic error in the program.
  • In a multiple-module program that contains only procedure-level (local) error handlers, if an enabled and inactive error handler cannot be found in the procedure where the error occurred, BASIC will search back through all the calling procedures as well as the module-level code of all the calling modules, looking for an enabled, inactive error handler.

Using Both Module-Level and Procedure-Level Error Handlers

  • For simplicity and clarity, it is a good idea to avoid using both local and procedure-level error handlers in the same program, except for using an error handler in the main module-level code as the last line of defense against a fatal error.
  • Despite the advice above, you can have both a module-level error handler and a local error handler enabled at the same time; in fact, both a local and a module-level error handler can be enabled from within a procedure.
  • While searching for an enabled, inactive error handler, BASIC may encounter an active event handler:
    • Unless an enabled error-handling routine is provided in the same module-level code as the event handler, BASIC generates a fatal error.
    • Therefore, to produce completely bullet-proof BASIC code in modules that trap events, make sure an error handler is enabled in the same module-level code as the event handler is enabled at the time the event occurs.
    Because event handlers can be located only at the module level, this is another special case where one might mix module-level and procedure-level error handlers.
  • Notice that when an error-handling routine is finished and program execution resumes through execution of a RESUME 0 or RESUME NEXT statement, the resume location is based on the location of the error-handling routine, and not necessarily on the location of where the error occurred. For more information, see RESUME .
Example

The program uses the ON ERROR statement to enable error trapping. The program attempts to write a large file to the disk. If an error occurs, control is passed to a handling routine, and the ERR function is used to determine an appropriate message to display. The ERROR, ERR, and RESUME statements are used to exit the handling routines, and the END, STOP, and SYSTEM statements demonstrate ways to exit a program.

DECLARE SUB ErrorMessage (Message$) DECLARE SUB WriteBigFile (Filenum%) ON ERROR GOTO ErrHandler CLS PRINT "This program will attempt to write a large file to a disk drive" PRINT "you select. The file will be erased when the program ends." PRINT DO INPUT "Which drive"; DR$ DR$ = UCASE$(DR$) LOOP UNTIL LEN(DR$) >= 1 AND LEN(DR$) <= 2 AND DR$ >= "A" AND DR$ <= "Z" IF LEN(DR$) > 1 THEN IF RIGHT$(DR$, 1) <> ":" THEN DR$ = LEFT$(DR$, 1) + ":" END IF ELSE DR$ = DR$ + ":" END IF 'Put together a complete file specification. FileSpec$ = DR$ + "BIGFILE.XXX" 'Get the next available file number. Filenum% = FREEFILE 'Try to open the file. OPEN FileSpec$ FOR OUTPUT AS Filenum% WriteBigFile Filenum% CLOSE Filenum% CLS PRINT "Everything was OK. No errors occurred." PRINT "Deleting the file that was created." KILL FileSpec$ 'Same as END, returns to operating system. SYSTEM ErrHandler: SELECT CASE ERR CASE 52 'Bad file name or number. END CASE 53 'File not found. RESUME NEXT CASE 57 'Device I/O error. ErrorMessage "You should probably format the diskette." END CASE 64 'Bad File Name. ErrorMessage "The drive name you specified was not correct." END CASE 68 'Device unavailable. ErrorMessage "The drive you named is unavailable." END CASE 71 'Drive not ready. ErrorMessage "The drive was not ready. Check the drive!" END CASE ELSE ErrorMessage "An unexpected FATAL error has occurred." STOP END SELECT SUB ErrorMessage (Message$) ON LOCAL ERROR GOTO MessageError CLS PRINT Message$ PRINT "Cannot continue." PRINT PRINT "Press any key to exit." DO LOOP WHILE INKEY$ = "" EXIT SUB MessageError: RESUME NEXT END SUB SUB WriteBigFile (Filenum%) ON LOCAL ERROR GOTO LocalHandler TEXT$ = STRING$(1024, "A") FOR I% = 1 TO 400 PRINT #Filenum%, TEXT$ NEXT I% EXIT SUB LocalHandler: SELECT CASE ERR CASE 61 'Disk full. ErrorMessage ("There is no room remaining on the disk.") KILL "BIGFILE.XXX" END CASE ELSE ERROR ERR END SELECT END SUB