**Debugging and Errors - errorInfo errorCode catch error return** !!!!!! '''[Tcl Tutorial Lesson 35%|%Previous lesson%|%]''' | '''[Tcl Tutorial Index%|%Index%|%]''' | '''[Tcl Tutorial Lesson 37%|%Next lesson%|%]''' !!!!!! In previous lessons we discussed how the `return` command could be used to return a value from a proc. In Tcl, a proc may return a value, but it always returns a status. When a Tcl command or procedure encounters an error during its execution, the global variable `errorInfo` is set, and an error condition is generated. If you have proc `a` that called proc `b` that called `c` that called `d` , if `d` generates an error, the "call stack" will unwind. Since `d` generates an error, `c` will not complete execution cleanly, and will have to pass the error up to `b` , and in turn on to `a`. Each procedure adds some information about the problem to the report. For instance: ====== proc a {} { b } proc b {} { c } proc c {} { d } proc d {} { some_command } a ====== ====== invalid command name "some_command" while executing "some_command" (procedure "d" line 2) invoked from within "d" (procedure "c" line 2) invoked from within "c" (procedure "b" line 2) invoked from within "b" (procedure "a" line 2) invoked from within "a" (file "errors.tcl" line 16) ====== Produces the following output:

This actually occurs when any exception condition occurs, including `break` and `continue`. The `break` and `continue` commands normally occur within a loop of some sort, and the loop command catches the exception and processes it properly, meaning that it either stops executing the loop, or continues on to the next instance of the loop without executing the rest of the loop body. It is possible to "catch" errors and exceptions with the `catch` command, which runs some code, and catches any errors that code happens to generate. The programmer can then decide what to do about those errors and act accordingly, instead of having the whole application come to a halt. A more flexible facility is the `try` command - see below. For example, if an `open` call returns an error, the user could be prompted to provide another file name. A Tcl proc can also generate an error status condition. This can be done by specifying an error return with an option to the `return` command, or by using the `error` command. In either case, a message will be placed in `errorInfo`, and the proc will generate an error. `error message ?info? ?code?`: Generates an error condition and forces the Tcl call stack to unwind, with error information being added at each step.

If `info` or `code` are provided, the errorInfo and errorCode variables are initialized with these values. `catch script ?varName?`: Evaluates and executes `script`. The return value of `catch` is the status return of the Tcl interpreter after it executes `script` If there are no errors in `script`, this value is 0. Otherwise it is 1. If `varName` is supplied, the value returned by `script` is placed in `varName` if the script successfully executes. If not, the error is placed in `varName`. `return ?-code code? ?-errorinfo info? ?-errorcode errorcode? ?value?`: Generates a return exception condition. The possible arguments are: %|%Code|Description%|% |`-code code` |The next value specifies the return status.| | |`code` must be one of the following words: | | |`ok` - Normal status return | | |`error` - Proc returns error status | | |`return` - Normal return | | |`break` - Proc returns break status | | |`continue` - Proc returns continue status | | | These allow you to write procedures that behave | | |like the built in commands `break`, `error`, and `continue`. | |`-errorinfo info`|`info` will be the first string in the `errorInfo` variable. | |`-errorcode errorcode`|The proc will set `errorCode` to `errorcode`. | |`value` |The string `value` will be the value returned by this proc. | `errorInfo`: `errorInfo` is a global variable that contains the error information from commands that have failed. `errorCode`: `errorCode` is a global variable that contains the error code from command that failed. This is meant to be in a format that is easy to parse with a script, so that Tcl scripts can examine the contents of this variable, and decide what to do accordingly. ---- ***Example*** ====== proc errorproc {x} { if {$x > 0} { error "Error generated by error" "Info String for error" $x } } catch errorproc puts "after bad proc call: ErrorCode: $errorCode" puts "ERRORINFO:\n$errorInfo\n" set errorInfo ""; catch {errorproc 0} puts "after proc call with no error: ErrorCode: $errorCode" puts "ERRORINFO:\n$errorInfo\n" catch {errorproc 2} puts "after error generated in proc: ErrorCode: $errorCode" puts "ERRORINFO:\n$errorInfo\n" proc returnErr { x } { return -code error -errorinfo "Return Generates This" -errorcode "-999" } catch {returnErr 2} puts "after proc that uses return to generate an error: ErrorCode: $errorCode" puts "ERRORINFO:\n$errorInfo\n" proc withError {x} { set x $a } catch {withError 2} puts "after proc with an error: ErrorCode: $errorCode" puts "ERRORINFO:\n$errorInfo\n" catch {open [file join no_such_directory no_such_file] r} puts "after an error call to a nonexistent file:" puts "ErrorCode: $errorCode" puts "ERRORINFO:\n$errorInfo\n" ====== <> Resulting output ======none after bad proc call: ErrorCode: TCL WRONGARGS ERRORINFO: wrong # args: should be "errorproc x" while executing "errorproc" after proc call with no error: ErrorCode: TCL WRONGARGS ERRORINFO: after error generated in proc: ErrorCode: 2 ERRORINFO: Info String for error (procedure "errorproc" line 1) invoked from within "errorproc 2" after proc that uses return to generate an error: ErrorCode: -999 ERRORINFO: Return Generates This invoked from within "returnErr 2" after proc with an error: ErrorCode: TCL READ VARNAME ERRORINFO: can't read "a": no such variable while executing "set x $a" (procedure "withError" line 2) invoked from within "withError 2" after an error call to a nonexistent file: ErrorCode: POSIX ENOENT {no such file or directory} ERRORINFO: couldn't open "no_such_directory/no_such_file": no such file or directory while executing "open [file join no_such_directory no_such_file] r" ====== <> !!!!!! '''[Tcl Tutorial Lesson 35%|%Previous lesson%|%]''' | '''[Tcl Tutorial Index%|%Index%|%]''' | '''[Tcl Tutorial Lesson 37%|%Next lesson%|%]''' !!!!!!