Sage-Code Laboratory
index<--

Nim Errors

Errors can occur in Nim for a variety of reasons, such as invalid syntax, runtime errors, and errors in library code. When an error occurs, the Nim compiler will generate a stack trace that shows the location of the error in the code.

In Nim exceptions are objects. By convention, exception types are suffixed with 'Error'. The system module defines an exception hierarchy that you might want to stick to. Exceptions derive from system.Exception, which provides the common interface.

Caution: A convention is that exceptions should be raised in exceptional cases, they should not be used as an alternative method of control flow. Exceptions are more expensive and you should not do large programs in exception handlers.

Error Handling in Nim

Nim has three types of errors:

Fatal Error

The "try" keyword is used to execute a block of code that may contain errors. The "except" keyword is used to handle errors that occur in the "try" block.


try:
    x = 1 / 0
except FatalError:
    print("Fatal error")

In this example, the "try" block attempts to divide 1 by 0. This will cause a fatal error, which is handled by the "except" block. The "except" block prints the message "Fatal error".

Errors

Errors can be handled by returning an error value from a function. For example, the following code shows how to handle an error by returning an error value:


func divide(x: int, y: int) -> int:
if y == 0:
    return Error
return x / y

Raise statement

Raising an exception is done with the raise statement. Before you can raise an exception you can define an initialize an error.


var
  e: ref OSError
new(e)
e.msg = "the request to the OS failed"
raise e

If the raise keyword is not followed by an expression, the last exception is re-raised. For the purpose of avoiding repeating this common code pattern, the template newException in the system module can be used:

raise newException(OSError, "the request to the OS failed")

Error handling

The "try" keyword is used to execute a block of code that may contain errors. The "except" keyword is used to handle errors that occur in the "try" block. The try statement handles exceptions:

try except

Try Statement

Example


from std/strutils import parseInt

# read the first two lines of a text file that should contain numbers
# and tries to add them
var
  f: File
if open(f, "numbers.txt"):
  try:
    let a = readLine(f)
    let b = readLine(f)
    echo "sum: ", parseInt(a) + parseInt(b)
  except OverflowDefect:
    echo "overflow!"
  except ValueError:
    echo "could not convert string to integer"
  except IOError:
    echo "IO error!"
  except CatchableError:
    echo "Unknown exception!"
    # reraise the unknown exception:
    raise
  finally:
    close(f)

Notes:

1.The statements after the try are executed unless an exception is raised. Then the appropriate except part is executed.

2.The empty except part is executed if there is an exception that is not explicitly listed. It is similar to an else part in if statements.

3.If there is a finally part, it is always executed after the exception handlers.

The exception is consumed in an except part. If an exception is not handled, it is propagated through the call stack. This means that often the rest of the procedure - that is not within a finally clause - is not executed (if an exception occurs).

If you need to access the actual exception object or message inside an except branch you can use the getCurrentException() and getCurrentExceptionMsg() procs from the system module.

Example:


try:
  doSomethingHere()
except CatchableError:
  let
    e = getCurrentException()
    msg = getCurrentExceptionMsg()
  echo "Got exception ", repr(e), " with message ", msg

Try this: Quiz