Try, Catch and Finally: Handle Failures

Report an invalid mark without pretending success

A school report receives mark -1. It should reject the input and explain the problem rather than save an invalid report or silently replace the mark.

try surrounds work that may throw. catch receives a thrown failure from that path. finally supplies cleanup work after ordinary completion or exception unwinding.

  1. Follow failure flow

    Identify statements skipped after a throw.

  2. Handle honestly

    Report a rejected input without claiming a successful save.

  3. Clean up

    Explain finally and the limits of a synchronous catch.

A thrown validation failure changes the path

  1. Try

    The mark violates a precondition.

    throw
  2. Catch

    Handle the known failure.

    Mark must be 0–50
  3. Finally

    Run the local cleanup path.

    Finished checking
Read these stages alongside the complete example. They explain the relationship; they do not execute code.

Catch handles a thrown failure, not every incorrect value

throw exits the current normal path and searches for an applicable handler. Statements after the throw in the same try path are skipped. An Error object carries a message and category.

A wrong average that does not throw will not automatically enter catch. Validate preconditions deliberately and catch only failures the surrounding code can handle appropriately.

Before starting, review error categories. These examples use JavaScript; other languages can use different syntax and rules.

Reject the mark and show the failure

The mark is negative, so the validation throws before the success output. catch prints the message and finally prints Finished checking.

This local example does not save a report. Its output tells the truth about the failed check.

JavaScript · local teaching example

try {
  const mark = -1;
  if (mark < 0 || mark > 50) throw new Error('Mark must be 0–50');
  console.log('Mark accepted');
} catch (error) {
  console.log(error.message);
} finally {
  console.log('Finished checking');
}

Expected output

Mark must be 0–50
Finished checking

A successful path still reaches finally

With a valid mark, no exception is thrown. The success statement runs, catch is skipped and finally still executes.

An error in cleanup can itself fail. Avoid returning from finally or suppressing earlier failures unintentionally.

JavaScript · local teaching example

try {
  const mark = 35;
  if (mark < 0 || mark > 50) throw new Error('Invalid mark');
  console.log('Mark accepted');
} catch (error) {
  console.log(error.message);
} finally {
  console.log('Finished checking');
}

Expected output

Mark accepted
Finished checking

Apply the rule to a small change

Reject mark 55 and use a message explaining the maximum, then print a final local completion message.

Worked answer

The success path is skipped. The handled message explains the range issue and the finally output confirms the checking routine ended, not that a report was saved.

JavaScript · local teaching example

try {
  const mark = 55;
  if (mark > 50) throw new Error('Maximum mark is 50');
  console.log('Accepted');
} catch (error) {
  console.log(error.message);
} finally {
  console.log('Check ended');
}

Expected output

Maximum mark is 50
Check ended

Recognize mistakes and limits

A try/catch around scheduling a later callback does not catch an exception thrown when that callback eventually runs on a different execution path. Promise rejections need a rejection handler or an awaited operation inside try/catch.

Do not catch everything and print “Saved.” Unexpected failures should remain diagnosable, often by rethrowing or recording useful context. User-facing messages should avoid exposing confidential data.

For the language or tool rules used here, see JavaScript errors and handling.

Check the core idea

JavaScript · code for this question

try {
  const mark = -1;
  if (mark < 0 || mark > 50) throw new Error('Mark must be 0–50');
  console.log('Mark accepted');
} catch (error) {
  console.log(error.message);
} finally {
  console.log('Finished checking');
}
Why does Mark accepted not appear for the invalid input?
Choose one answer. You can try again.

Answer and explanation

Throw leaves that normal path before the success statement.

Yes. Control goes to the handler.

Apply the idea to a new situation

Does catch automatically identify a wrong average that never throws?
Choose one answer. You can try again.

Answer and explanation

No, catch handles thrown failures from the applicable path.

Yes. A logic error needs tests or checks that detect it.

Handle the failed operation without hiding its outcome

Throw interrupts a path, catch handles the failure and finally supplies cleanup. Preserve diagnostic meaning and handle asynchronous failures through their actual result mechanism.

Connect this idea with specific failure categories and awaited error handling.

Reaching the recap and completing the quizzes are separate milestones.

    Next lesson: Custom Exceptions: Meaningful Error Categories →