Dart Exception Handling

Handle errors gracefully in your Dart applications

🛡️ What is Exception Handling?

Exception handling helps your program deal with unexpected errors gracefully instead of crashing. Use try-catch blocks to catch and handle exceptions that might occur during program execution.


void main() {
  try {
    int result = 10 ~/ 0; // Division by zero
    print(result);
  } catch (e) {
    print('Error caught: $e');
  }
  print('Program continues...');
}
                                    

Output:

Error caught: IntegerDivisionByZeroException

Program continues...

Exception Handling Concepts

🎯

Try-Catch

Basic exception handling structure

try {
  // risky code
} catch (e) {
  // handle error
}
🔧

Finally Block

Code that always executes

try {
  // code
} finally {
  // cleanup
}
🚀

Throw Exception

Create custom exceptions

if (age < 0) {
  throw Exception('Invalid age');
}
📝

Specific Catches

Handle different exception types

} on FormatException {
  // handle format error
}

🔹 Basic Try-Catch

Handle exceptions with try-catch blocks:

void main() {
  // Example 1: Division by zero
  try {
    int a = 10;
    int b = 0;
    int result = a ~/ b;
    print('Result: $result');
  } catch (e) {
    print('Caught exception: $e');
  }
  
  // Example 2: Invalid string to number conversion
  try {
    String text = 'abc';
    int number = int.parse(text);
    print('Number: $number');
  } catch (e) {
    print('Cannot convert "$text" to number: $e');
  }
  
  print('Program finished successfully!');
}

Output:

Caught exception: IntegerDivisionByZeroException

Cannot convert "abc" to number: FormatException: Invalid radix-10 number (at character 1)

Program finished successfully!

🔹 Specific Exception Types

Catch specific types of exceptions:

void processData(String data) {
  try {
    // Try to parse as number
    int number = int.parse(data);
    
    // Try to access list element
    List<int> numbers = [1, 2, 3];
    print('Value at index $number: ${numbers[number]}');
    
  } on FormatException {
    print('Error: "$data" is not a valid number');
  } on RangeError {
    print('Error: Index out of range');
  } catch (e) {
    print('Unexpected error: $e');
  }
}

void main() {
  processData('abc');    // Format exception
  processData('5');      // Range exception
  processData('1');      // Success
}

Output:

Error: "abc" is not a valid number

Error: Index out of range

Value at index 1: 2

🔹 Finally Block

Code that runs regardless of exceptions:

void readFile(String filename) {
  print('Opening file: $filename');
  
  try {
    if (filename.isEmpty) {
      throw Exception('Filename cannot be empty');
    }
    
    if (filename == 'missing.txt') {
      throw Exception('File not found');
    }
    
    print('Reading file content...');
    print('File read successfully!');
    
  } catch (e) {
    print('Error reading file: $e');
  } finally {
    print('Closing file resources...');
    print('Cleanup completed.');
  }
}

void main() {
  readFile('data.txt');      // Success case
  print('---');
  readFile('missing.txt');   // Error case
  print('---');
  readFile('');              // Another error case
}

Output:

Opening file: data.txt

Reading file content...

File read successfully!

Closing file resources...

Cleanup completed.

---

Opening file: missing.txt

Error reading file: Exception: File not found

Closing file resources...

Cleanup completed.

---

Opening file:

Error reading file: Exception: Filename cannot be empty

Closing file resources...

Cleanup completed.

🔹 Throwing Custom Exceptions

Create and throw your own exceptions:

// Custom exception class
class InvalidAgeException implements Exception {
  final String message;
  InvalidAgeException(this.message);
  
  @override
  String toString() => 'InvalidAgeException: $message';
}

class Person {
  String name;
  int age;
  
  Person(this.name, this.age) {
    if (age < 0) {
      throw InvalidAgeException('Age cannot be negative: $age');
    }
    if (age > 150) {
      throw InvalidAgeException('Age seems unrealistic: $age');
    }
  }
  
  @override
  String toString() => '$name (age: $age)';
}

void main() {
  try {
    var person1 = Person('Alice', 25);
    print('Created: $person1');
    
    var person2 = Person('Bob', -5);  // This will throw
    print('Created: $person2');
    
  } on InvalidAgeException catch (e) {
    print('Custom exception caught: $e');
  } catch (e) {
    print('Other exception: $e');
  }
  
  try {
    var person3 = Person('Charlie', 200);  // This will also throw
  } catch (e) {
    print('Caught: $e');
  }
}

Output:

Created: Alice (age: 25)

Custom exception caught: InvalidAgeException: Age cannot be negative: -5

Caught: InvalidAgeException: Age seems unrealistic: 200

🧠 Test Your Knowledge

What happens if you don't handle an exception in Dart?