CodeBlanks Logo Icon CodeBlanks

Error handling

Add error handling with try/catch.

Error handling

If you call a non-existent index on a list Dart throws a RangeError. The program crashes on that error. But with try/catch you catch the error and show a friendly message; the program keeps running.

For example on a two-book list calling books[5] throws. With try { print(books[5].title); } catch (e) { print("book not found"); } you catch the error and show a friendly message. This is what makes real applications resilient; unexpected cases become a friendly reply instead of a crash.

The try/catch pattern

In this project we use try/catch in this case: the user asks for a book number, the number is not in the list, a RangeError is thrown. catch catches it and prints "book not found". So the program keeps running even when a book is missing.

A good application is resilient to errors. Alongside try/catch you sometimes also do an explicit if (index < books.length) check; this prevents the error up front. Which one to pick depends on the case. try/catch is more general; if is more explicit. We will try try/catch in this lesson.

Practice Catch an out-of-range access

The Library and Book classes plus a two-book list are already defined in the code below. Inside a try block call print(books[5].title); this throws an out-of-range error. In a catch (e) block print "book not found". The program gives a message instead of crashing.

Starter code

main.dart
class Library {
  String name;
  Library(this.name);
  void info() {
    print("Library: $name");
  }
}

class Book {
  String title;
  Book(this.title);
}

void main() {
  final lib = Library("City");
  lib.info();
  final b = Book("Crime and Punishment");
  print("New book: ${b.title}");
  final books = <Book>[Book("Crime and Punishment"), Book("Les Mis")];
  print("Count: ${books.length}");
  print("First: ${books[0].title}");
  // try the index 5 access; print a message in catch
}

Sample solution

main.dart
class Library {
  String name;
  Library(this.name);
  void info() {
    print("Library: $name");
  }
}

class Book {
  String title;
  Book(this.title);
}

void main() {
  final lib = Library("City");
  lib.info();
  final b = Book("Crime and Punishment");
  print("New book: ${b.title}");
  final books = <Book>[Book("Crime and Punishment"), Book("Les Mis")];
  print("Count: ${books.length}");
  print("First: ${books[0].title}");
  try {
    print(books[5].title);
  } catch (e) {
    print("book not found");
  }
}

Expected output

Library: City
New book: Crime and Punishment
Count: 2
First: Crime and Punishment
book not found

Questions and answers

Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.

1 Match error handling

Term Meaning
RangeError out-of-range access
try holds risky code
catch catches the error
print writes the message

2 When does control leave the try block?

main.dart
try {
  print(books[5].title);
} catch (e) {
  print("none");
}
  • When an error is thrown
  • When print runs
  • When main starts
  • Never Correct answer

Explanation: an error inside try passes control to catch.

3 The catch block

Question
try {
  print(books[5].title);
} ____ (e) {
  print("no book");
}
Answer
try {
  print(books[5].title);
} catch (e) {
  print("no book");
}

Explanation: Write catch; followed by (e) parameter and block.

All lessons in Beginner