Home
Starting Up
Tech
Creators
A.I.
Lifestyle
Money
Idea Board
Vibe Coding Tools
Products
Ideas DB
Case Studies DB
Subscribe to IH+
Starting Up
Tech
A.I.
Creators
Lifestyle
Money
Join
6
Likes
0
Bookmarks
13
Comments
Report
Hate Writing Try...Catch In Node.js? Do This Instead
by
Kyle
https://www.youtube.com/watch?v=s5YoXms0ECs
Trending on Indie Hackers
I spent $0 on marketing and got 1,200 website visitors - Here's my exact playbook
67 comments
Veo 3.1 vs Sora 2: AI Video Generation in 2025 🎬🤖
31 comments
I built eSIMKitStore — helping travelers stay online with instant QR-based eSIMs 🌍
21 comments
🚀 Get Your Brand Featured on FaceSeek
20 comments
Day 6 - Slow days as a solo founder
16 comments
Why I'm Done Juggling 10 SaaS Tools (And You Should Be Too)
9 comments
This isn't really nodejs, as so much as it is express.
While this works, it just isn't a good pattern to use for a number of reasons. First of all it doesn't well track your errors, it doesn't provide good handling when you want to capture the problem.
And most problematic is that it isn't better than the alternative. Here's why:
use
might go unnoticed, making the whole pattern moot.Better than doing this at all, is to just rely on the framework patterns. openapi-factory uses middleware, express uses error function fallbacks, etc... Almost every framework has one, just use those, and stop trying to reinvent a different pattern in node.
Hi Warren, while I do understand your concerns, I still like this solution for one main reason: Express was born before we had async/await...
I guess if they were to create Express today, they would send any uncaught error to the
next(err)
handler... next(err) is idiomatic nodejs error handling, try/catch isn't.So I think Kyle's approach is actually a good solution to solve the impedance mismatch between the old Express and async/await :)
Another option is to use a Promise syntax instead of await... and add
.catch(next)
to it.Sure, it's not idiomatic express, and you can forget the HOF or
catch(next)
, but async/await isn't idiomatic express anyway...Hey Warren, thank you for the reply. The core of the example is the HOF, and while the final error handler is Express-specific, this can easily be adapted for other frameworks, or handle the error in the HOF itself.
I'm not sure how it will not track the errors? It will catch the errors exactly the same as a try...catch statement and these can be logged like any other error message.
Re: your second point - there's no guarantee that a developer will properly wrap every method in a try...catch statement either.
A global error handler is definitely something that should be in every web project, but with some caveats.
As mentioned in @wparad's comment, newer developers could miss the
use
function, and then you have subtle bugs in your code - the worst kind. Thankfully, this can largely be fixed by patching express a little so that it works as you'd expect, even for async errors.Also, I wouldn't use this for all errors. In the global error handler for Nodewood, I try to catch specific 4xx-class errors first and use them to display specific API messages that the UI knows how to consume, then display a generic 500 message for everything else.
But there are all kinds of places where try/catch makes a lot of sense. For example, if a user hits a unique error when trying to insert into the DB, you can try/catch that and use it to re-throw a more-specific error message that your global error handler can then display directly, with safe-to-display error text. You still use try/catch all over your app, but not as repeated boilerplate, instead to add more application-specific smarts and error handling.
Thanks Dan! Yes, I agree - try/catch is still useful for handling bespoke errors.
For database errors, I always validate the input before inserting to prevent a MySQL error, and throw custom errors - which gets picked up by the global handler and sent back to the client.
Ah, that might be personal preference - I prefer to assume the insert will work and catch the "duplicate unique" error. It saves having to make the DB call to check if it's unique in the first place, and prevents race conditions where that first call says there's no duplicate value, then the value is inserted in another thread, and when we try to actually insert, the value already exists.
Maybe a better example is a third-party API. You can validate those all you want, but sometimes they will reply with an error that has to be handled, and many libraries express this through a thrown error.
But anyway, I'm pretty sure we're on the same page here - "a few, specifically targeted try/catch" > "try catch in practically every function by default."
I only skimmed through the video, but I think I got the gist of it.
Handling errors in your middleware is not a bad idea, but a catch-all is probably not the solution. It's really only useful as a fallback for parts of your code where you only implement the happy path at first.
My tips:
error-instance-id
.Then when a user tells you: "I did action A, B, and C and then I got an internal server error", you can look up that exact error in Sentry.
I use Sentry, adding the uuid is a smart touch :)
That reminds me of an alternative pattern for try/catch. I think it's inspired by philosophies in the Go programming language. The "happy code path" is the least indented, so it's easy to visually follow the non-error flow of the program.
When an
if (error)
happens the code is indented with error handling logic. This gives a nice separation between the happy path and the error path.If you like this style, use it. But remember your teammates might not "get it" at first. 😉
PS. I like it. 😎
It's definitely nicer than try/catch Marcus! The extra if statements are a lot of extra work though :D
Yeah, you're right about that. I like that it's explicit but still pretty short. The extra work isn't too bad, especially if the first and second promise produce different types of errors handles different types of errors. One might be a network request and the other a file system interaction.
I have too admit that I only skimmed the video on mute, but was the suggested pattern applicable outside of the express server example?
I'm always looking for neat tricks like this to expand my toolbox. :)
Yes, it'll work with any framework. I'm essentially wrapping the API handlers in a HOF, so any errors in controller and model methods will be caught in one place.
You just need to use the HOF to wrap the handler at the highest entry point in your application.
Ah, yes. I think that's how I understood it: "with any framework".
It's a very nice pattern for that. :)