Skip to main content
Dart utilizes try, on, catch, and finally blocks to implement structured exception handling. This mechanism intercepts runtime exceptions thrown within a designated scope, allowing for flow control management, object capture, and resource cleanup.

Syntax Structure

The exception handling structure allows for specific type matching, object capturing, and unconditional execution.
try {
  // Code that may throw an exception
} on SpecificExceptionType {
  // Handles exceptions of type SpecificExceptionType
} catch (e, s) {
  // Handles any exception not caught by previous 'on' blocks
  // e: The exception object
  // s: The StackTrace object (optional)
} finally {
  // Code that executes regardless of success or failure
}

Components

The try Block

Defines the lexical scope in which exceptions are monitored. If an exception is thrown within this block, control flow immediately transfers to the nearest matching handler.

The on Clause

Specifies the type of exception to handle. This is used when the handling logic differs based on the class of the thrown exception. Multiple on clauses can be chained; Dart evaluates them in top-down order.
try {
  methodThrowingInt();
} on int {
  print('Caught an integer exception');
} on Exception {
  print('Caught a standard Exception');
}

The catch Block

Captures the exception object. This block is required if the handler needs to inspect the value of the exception or access the stack trace. It can be used in conjunction with on or independently to handle all exceptions. catch accepts up to two positional arguments:
  1. Exception Object: The actual object thrown (typically a subtype of Exception or Error, though Dart allows throwing any non-null object).
  2. StackTrace: An object containing the record of the call stack at the point the exception was thrown.
try {
  // ...
} on FormatException catch (e) {
  // Captures the exception object 'e' specifically for FormatException
  print(e.message);
} catch (e, s) {
  // Captures exception 'e' and stack trace 's' for all other types
  print('Exception: $e');
  print('Stack trace: $s');
}

The finally Block

Contains code that executes unconditionally. The finally block runs after the try and catch blocks complete, regardless of whether an exception was thrown or caught. If the try block exits via return, break, or continue, the finally block executes immediately prior to that exit.
try {
  openResource();
  operate();
} catch (e) {
  handleError(e);
} finally {
  closeResource(); // Executes whether operate() succeeds or fails
}

Propagating Exceptions (rethrow)

The rethrow keyword allows a caught exception to be passed up the call stack. Unlike throwing a new exception, rethrow preserves the original exception object and its original stack trace.
try {
  riskyOperation();
} catch (e) {
  logError(e); // Perform partial handling (e.g., logging)
  rethrow;     // Pass control to the caller's exception handler
}
Master Dart with Deep Grasping Methodology!Learn More