10 min read

Eye Training · try / catch / finally

A try only protects what actually fails inside it. Most error-handling bugs are about what slips out.

Part 2 · Surface 11. Bug counts are hidden and some snippets are clean. See Start Here for how to use these drills.


J · The basics

Bug hunt
J · Load the config
Bug count hidden, and some snippets are clean. Click every line you think is wrong (or none), then check.
0:00 / 1 min
Bug hunt
J · Save the profile
Bug count hidden, and some snippets are clean. Click every line you think is wrong (or none), then check.
0:00 / 1 min
Bug hunt
J · Read the cache file
Bug count hidden, and some snippets are clean. Click every line you think is wrong (or none), then check.
0:00 / 1 min
Bug hunt
J · Parse or null
Bug count hidden, and some snippets are clean. Click every line you think is wrong (or none), then check.
0:00 / 1 min
Bug hunt
J · Charge the order
Bug count hidden, and some snippets are clean. Click every line you think is wrong (or none), then check.
0:00 / 1 min

M · Three years in, these should jump out

Bug hunt
M · Read with a fallback
Bug count hidden, and some snippets are clean. Click every line you think is wrong (or none), then check.
0:00 / 1 min
Bug hunt
M · Get the user
Bug count hidden, and some snippets are clean. Click every line you think is wrong (or none), then check.
0:00 / 1 min
Bug hunt
M · Run with a lock
Bug count hidden, and some snippets are clean. Click every line you think is wrong (or none), then check.
0:00 / 1 min
Bug hunt
M · Import products
Bug count hidden, and some snippets are clean. Click every line you think is wrong (or none), then check.
0:00 / 2 min
Bug hunt
M · Validate the amount
Bug count hidden, and some snippets are clean. Click every line you think is wrong (or none), then check.
0:00 / 1 min
Bug hunt
M · Get an order
Bug count hidden, and some snippets are clean. Click every line you think is wrong (or none), then check.
0:00 / 1 min
Bug hunt
M · Read JSON with a callback
Bug count hidden, and some snippets are clean. Click every line you think is wrong (or none), then check.
0:00 / 2 min
Bug hunt
M · Transfer money
Bug count hidden, and some snippets are clean. Click every line you think is wrong (or none), then check.
0:00 / 2 min
Bug hunt
M · Use a client
Bug count hidden, and some snippets are clean. Click every line you think is wrong (or none), then check.
0:00 / 1 min
Bug hunt
M · Load an invoice
Bug count hidden, and some snippets are clean. Click every line you think is wrong (or none), then check.
0:00 / 1 min

S · Where seniors stand out

Bug hunt
S · Retry helper
Bug count hidden, and some snippets are clean. Click every line you think is wrong (or none), then check.
0:00 / 2 min
Bug hunt
S · Report route (Express 4)
Bug count hidden, and some snippets are clean. Click every line you think is wrong (or none), then check.
0:00 / 1 min
Bug hunt
S · Process-level handlers
Bug count hidden, and some snippets are clean. Click every line you think is wrong (or none), then check.
0:00 / 1 min

What your eye checks

Whenever you see a try, ask:

  1. Is the failure actually inside it? Missing await, a return without await, or a callback that runs later all escape the try.
  2. What does the catch do with it? Swallow it, log and carry on, convert it, or rethrow it? Does the caller find out?
  3. Can the catch itself throw? A wrong variable name, a property of undefined, or another await in the catch.
  4. Which errors does it catch, and what does it turn them into? A catch-all that maps everything to 404, null or "invalid input" hides real outages.
  5. Is the original error kept? Throw Error objects, never strings, and wrap with { cause: err }.
  6. Is the half-done work undone? A transaction needs a rollback; a multi-step change needs compensation.
  7. Is finally only cleaning up? No return or throw in it, and the resource is acquired before the try.
  8. Retries: is the error retryable, is the work idempotent, and is there backoff with jitter?

Tells

The visual cue that should make your eye stop:

You seeAsk
A call without await inside a tryDoes the rejection escape the try?
return somePromise inside a tryShould it be return await?
catch {} or catch (e) { log(e) }Is the failure hidden from the caller?
throw 'text'Where's the stack trace?
catch that returns a fixed statusDoes a timeout become a 404?
return inside finallyWhat happened to the result and the error?
fs.readFile(…, (err, …) => { throw err })Who catches a throw in a callback?
BEGIN … catch with no ROLLBACKWhat state is the connection returned in?
A retry loop with a fixed sleepWhich errors, which operations, and how many clients at once?
async (req, res) => without tryExpress 4 or 5?

Go deeper