catch handles thrown exceptions, while finally runs whether the protected work succeeds or fails.

Program

Play the program to see cleanup happen on both the normal path and the failure path.

shouldFail
try_catch_finally.dart
Replay: real traced execution (multi-file project)
void main() {
  var shouldFail = false;
  var log = <String>[];
  try {
    log.add('open');
    if (shouldFail) throw StateError('boom');
    log.add('work');
  } catch (e) {
    log.add('catch');
  } finally {
    log.add('close');
  }
  print(log.join('>'));
}
void main() {
  var shouldFail = true;
  var log = <String>[];
  try {
    log.add('open');
    if (shouldFail) throw StateError('boom');
    log.add('work');
  } catch (e) {
    log.add('catch');
  } finally {
    log.add('close');
  }
  print(log.join('>'));
}
  1. shouldFail ← false

    1void main() {2  var shouldFail = false;3  var log = <String>[];
    values this stepfalseshouldFail
  2. log ← []

    2var shouldFail = false;3var log = <String>[];4try {
    values this step[]log
  3. log ← [open]

    4try {5  log.add('open');6  if (shouldFail) throw StateError('boom');
    values this step[] [open]log
  4. throw ← false

    5log.add('open');6if (shouldFail) throw StateError('boom');7log.add('work');
    values this stepfalsethrowfalseshouldFail
  5. log ← [open, work]

    6  if (shouldFail) throw StateError('boom');7  log.add('work');8} catch (e) {
    values this step[open] [open, work]log
  6. log ← [open, work, close]

    10} finally {11  log.add('close');12}
    values this step[open, work] [open, work, close]log
  7. print(log.join('>'));

    12  }13  print(log.join('>'));14}
    outputopen>work>close
    values this step[open, work, close]log
  1. shouldFail ← true

    1void main() {2  var shouldFail = true;3  var log = <String>[];
    values this steptrueshouldFail
  2. log ← []

    2var shouldFail = true;3var log = <String>[];4try {
    values this step[]log
  3. log ← [open]

    4try {5  log.add('open');6  if (shouldFail) throw StateError('boom');
    values this step[] [open]log
  4. throws ← StateError('boom')

    5log.add('open');6if (shouldFail) throw StateError('boom');7log.add('work');
    values this stepStateError('boom')throwstrueshouldFail
  5. log ← [open, catch]

    8} catch (e) {9  log.add('catch');10} finally {
    values this step[open] [open, catch]log
  6. log ← [open, catch, close]

    10} finally {11  log.add('close');12}
    values this step[open, catch] [open, catch, close]log
  7. print(log.join('>'));

    12  }13  print(log.join('>'));14}
    outputopen>catch>close
    values this step[open, catch, close]log
try The `try` block contains work that might throw.
catch `catch (e)` runs only for the thrown path.
finally `finally` always runs, making it suitable for cleanup.