Exception Handling

Sometimes things go wrong at runtime: a file is missing, a network connection drops, or you accidentally divide by zero. Exception handling allows you to catch these errors and react to them, instead of letting your script crash.

The Try...Except Block

Use try...except to wrap code that might fail. If an error occurs, the except block is executed.

try
  // Risky code
  var zero := 0;
  var x := 1 div zero;
except
  on E: Exception do
    PrintLn('An error occurred: ' + E.Message);
end;
Result
An error occurred: Division by zero *

You can catch specific types of exceptions using the on E: ExceptionType do syntax. The else clause can be used as a catch-all.

The Try...Finally Block

The finally block is guaranteed to execute whether an exception occurred or not. This is perfect for cleaning up resources like closing files or freeing objects.

If you use exit to leave a function early from within a try block, the finally block still runs before the function actually returns.

Combined Try...Except...Finally

DWScript allows you to combine both into a single block. The except part handles errors, and the finally part handles cleanup.

var f : File;
try
  f := FileOpen('data.txt', fmOpenRead);
  // Read file...
  if f.Size = 0 then
    raise new Exception('File is empty');
except
  on E: Exception do
    PrintLn('Error: ' + E.Message);
finally
  if f.IsValid then f.Close;
end;
Result
Error: Invalid file handle *

Raising Exceptions

You can trigger exceptions manually using the raise keyword. You can create a generic exception or define your own custom exception classes by inheriting from Exception.

type EMyError = class(Exception);

try
  raise new EMyError('Something custom happened');
except
  on E: EMyError do
    PrintLn(E.Message);
end;
Result
Something custom happened

Assertions

Assertions are a way to check if a condition is true during development. If the condition is false, an EAssertionFailed exception is raised.

var x := -1;
try
  Assert(x > 0, 'x must be positive');
except
  on E: Exception do
    PrintLn(E.Message);
end;
Result
Assertion failed * : x must be positive

Re-raising Exceptions

Sometimes you want to log an error but still let it propagate up to a higher-level handler. Using raise without an argument inside an except block re-raises the current exception.

procedure Log(msg: String); begin PrintLn(msg); end;

try
  try
     raise new Exception('Original Error');
  except
     on E: Exception do begin
        Log('Error: ' + E.Message);
        raise; // Re-throw
     end;
  end;
except
   on E: Exception do ; // Suppress for demo
end;
Result
Error: Original Error

Stack Traces

When an exception is caught, you can inspect its StackTrace property to see exactly where the error occurred and the sequence of calls that led to it. This is invaluable for debugging complex scripts.

try
  raise new Exception('Error');
except
  on E: Exception do
    if E.StackTrace <> '' then PrintLn('Stack trace available');
end;
Result
Stack trace available

ExceptObject

The ExceptObject magic function gives you access to the exception object currently being handled. It returns an Exception instance that is automatically populated within an except or finally block.

This is particularly useful in finally blocks to check if an exception is currently active, or in except blocks when you aren't using the on E: Exception binding.

Native Exceptions (EDelphi)

When the host application (the Delphi environment running the script) throws an error that isn't caught by the host, it is wrapped in an EDelphi exception object before being passed to your script.

EDelphi inherits from Exception and adds an ExceptionClass property, which contains the name of the original Delphi exception class (e.g., 'EExternalException' or 'EAccessViolation').

try
  // Call to a native function that fails at runtime
  var fmt := '%d';
  var s := Format(fmt, ['not a number']);
except
  on E: EDelphi do begin
    PrintLn('Native error of type: ' + E.ExceptionClass);
  end;
  on E: Exception do begin
    PrintLn('Exception: ' + E.Message);
  end;
end;
Result
Native error of type: EScriptError
On this page