Exception Handling

Exceptions provide a structured way to handle runtime errors and unexpected conditions.

Try...Except

Use try...except to catch and handle exceptions. This allows your program to recover from errors gracefully rather than crashing.

var data : array of Integer := [ 1, 2, 3 ];

try
   PrintLn(data[10]);
except
   on E: Exception do
      PrintLn('Error: ' + E.Message);
end;
Result
Error: Upper bound exceeded! Index 10*

Try...Finally

Use try...finally to ensure code runs regardless of whether an exception occurs. This is essential for resource cleanup, such as closing files or freeing memory.

PrintLn('Starting');
try
  PrintLn('Working...');
finally
  PrintLn('Cleanup');
end;
Result
Starting
Working...
Cleanup

Combined Try...Except...Finally

You can nest try blocks or combine them to handle errors and ensure cleanup. A common pattern is protecting a resource that must be closed even if an operation fails.

var connectionOpen := True;
try
  try
    // Perform work that might fail
    raise new Exception('Connection lost');
  except
    on E: Exception do
      PrintLn('Caught: ' + E.Message);
  end;
finally
  connectionOpen := False;
  PrintLn('Connection closed');
end;
Result
Caught: Connection lost
Connection closed

Raising Exceptions

You can raise exceptions using the raise keyword.

procedure CheckAge(age: Integer);
begin
  if age < 0 then
    raise new Exception('Age cannot be negative');
end;

try
  CheckAge(-5);
except
  on E: Exception do
    PrintLn(E.Message);
end;
Result
Age cannot be negative

The "on...do" Syntax

You can handle specific exception types.

type EMyError = class(Exception);

try
  raise new EMyError('Custom error');
except
  on E: EMyError do
    PrintLn('Specific catch: ' + E.Message);
  on E: Exception do
    PrintLn('General catch: ' + E.Message);
end;
Result
Specific catch: Custom error

Catch-All "else"

You can use an else clause to catch any exception that wasn't matched by previous on blocks.

try
  raise new Exception('Something went wrong');
except
  on E: EAssertionFailed do
    PrintLn('Assertion failed');
  else
    PrintLn('Caught unknown error: ' + ExceptObject.Message);
end;
Result
Caught unknown error: Something went wrong

Exception Object

Within an except block, the ExceptObject function returns the exception instance being handled.

try
  raise new Exception('Fail');
except
  PrintLn(ExceptObject.Message);
end;
Result
Fail

Re-raising Exceptions

You can re-raise the current exception using raise with no arguments.

try
  try
    raise new Exception('Critical failure');
  except
    PrintLn('Logging error...');
    raise; // Re-throw to outer handler
  end;
except
  on E: Exception do
    PrintLn('Outer catch: ' + E.Message);
end;
Result
Logging error...
Outer catch: Critical failure

Exception Best Practices

  • Catch specific exceptions whenever possible rather than using a general on E: Exception.
  • Use finally blocks to ensure resources like database connections or temporary files are always closed.
  • Don't suppress exceptions with an empty except block unless you have a very specific reason to do so.
On this page