Exceptions and Error Handling
Prerequisites: Classes and objects
When something goes wrong while a program runs, Dart throws an exception. If nothing catches it, the program stops.
Real-world analogy: an exception is a fire alarm. catch is the
plan for what to do when it goes off.
try, on, catch, finally
void main() {
for (final input in ['42', 'abc']) {
try {
final n = int.parse(input);
print('Parsed $n');
} on FormatException catch (e) {
print('Not a number: ${e.source}');
} finally {
print("Done with '$input'");
}
}
}
Parsed 42
Done with '42'
Not a number: abc
Done with 'abc'
on Typecatches a specific kind of exception;catch (e)gives you the exception object. You can use either or both.finallyruns no matter what — for cleanup.
Throwing and custom exceptions
class InsufficientFundsException implements Exception {
final double shortfall;
InsufficientFundsException(this.shortfall);
@override
String toString() => 'Insufficient funds: short by $shortfall';
}
double withdraw(double balance, double amount) {
if (amount <= 0) throw ArgumentError.value(amount, 'amount', 'must be positive');
if (amount > balance) throw InsufficientFundsException(amount - balance);
return balance - amount;
}
void main() {
try {
withdraw(50, 80);
} on InsufficientFundsException catch (e) {
print(e);
print('Please deposit ${e.shortfall}');
}
try {
withdraw(50, -5);
} on ArgumentError catch (e) {
print(e.message);
}
}
Insufficient funds: short by 30.0
Please deposit 30.0
must be positive
Exception vs Error
Dart separates two kinds of problem:
Exception— an expected failure the program should handle: bad input, a missing file, a network timeout.Error— a bug in the program: calling a method with invalid arguments (ArgumentError), an index out of range (RangeError),!onnull. These generally shouldn't be caught — fix the code instead.
Implement Exception for your own recoverable failures.
rethrow
Inside a catch, rethrow passes the same exception on after, say,
logging it.
Common mistakes
- A bare
catch (e)everywhere, hiding bugs. Catch the specific types you can handle. - Using exceptions for normal outcomes. If "not found" is expected,
returning
nullor a sealed result type is often clearer.
Practice
Write int parseAge(String text) that throws a FormatException with a
helpful message if the text isn't a number or isn't between 0 and 150.
Call it with '200' in a try/on block and print the message.
Show solution
int parseAge(String text) {
final age = int.tryParse(text);
if (age == null) throw FormatException("'$text' is not a number");
if (age < 0 || age > 150) throw FormatException('Age $age is out of range (0-150)');
return age;
}
void main() {
try {
parseAge('200');
} on FormatException catch (e) {
print('Error: ${e.message}');
}
}
Error: Age 200 is out of range (0-150)