June 9th, 2025 ×
Handling and Throwing Errors

Wes Bos Host

Scott Tolinski Host
Transcript
Wes Bos
Welcome to Syndax today. We have an episode for you on errors, how to handle them, how to throw them, what what they contain.
Wes Bos
Our application is full of of errors. I I I write a lot of errors myself and how to structure your application so that you can handle them appropriately on the client, on the server, how to throw your own custom errors, what to do with them, when you should be throwing one versus returning some data just with some errors in it is is kind of a tricky thing. So we're gonna we're gonna dive on into it and try to explain all of those pieces. My name is Wes Bos, developer from Node. With me, as always, is Scott. How are you doing today, Scott?
Scott Tolinski
I'm doing alright.
Scott Tolinski
Quick trip to the urgent care for a cut finger this morning, but, hey, man.
Scott Tolinski
Yeah. Not the first time, Wes. Time? Yes. Oh my gosh.
Scott Tolinski
I know how many I don't know how many times Wes has gotten the message that, hey. I'm gonna be a little bit late. Gotta head to the urgent care. Hurt myself in some way.
Scott Tolinski
So, yeah, they glued they glued me up.
Scott Tolinski
I'm good to go. And, yeah.
Scott Tolinski
Feeling feeling like this is just my life. That's just how it goes. I gotta chill out, I think.
Wes Bos
Alright. Well, let's get on into it. We're first going to dive into explaining a few specific words about error and error handling. Then we'll get into what's in an error, and then we'll dive into all of the different types of errors that can be thrown, how to deal with the synchronous versus synchronous code, client side versus server side, and then, like, what do you actually do with them? So first of all, the wording around errors, specifically, we're talking about JavaScript here, but this will work in a lot of other languages JS the whole idea of, like, thrown and catching.
Wes Bos
So when you have an error, whether it's in your own code, whether it's in, like, a a module that you you have have done or whether it's, like, something that you did not totally expect, like your your application has a syntax error in it somewhere, that is the word that we use there is is thrown. Right? An error is thrown. And then when you want to handle that error, the word that we use there is is catch. So simply like it's Scott has here, it's like throwing a ball, but it makes you sad.
Wes Bos
Something went wrong. You simply throw it. This didn't work. You throw it out there, and then somewhere else in your application, you are going to need to handle that. You're gonna have to catch that specific error, and then do something with it, whether that is logging it out, whether that is displaying some UI to your user, whether that is retrying that specific logic.
Scott Tolinski
Yeah. I do like that that visual of throwing a ball because it is just like, I got a problem over here. Sad. Yes. Yeah. Now you're gonna have a problem over there, and and how will you handle it, is is up to you, but there's numerous ways of taking care of that from there. Yeah. Inside of an error is a few things. Because when you throw an error, you are using the keyword throw, and you sometimes you have in here that you don't need to use the word new. Sometimes you use the word throw new and then capital e error and then what happened, but, like, why don't you need the keyword new? I'm curious about that.
Wes Bos
Yeah. Yeah. You don't need the new keyword when you Yarn throwing. So if you're simply just throwing a new error, you can you can just throw error.
Wes Bos
If you do want to construct the error ahead of time, you're creating a new class. And in that case, you have to then create a new one, and then you can throw it at a later ESLint, but the new keyword is not necessary, which I had no idea. I was adding new for probably my entire career, but the thing is the perf. I could've in the time, I could've saved
Scott Tolinski
without typing a new instructing a new instance. And and even if there there's some, you know, thought there too if if you're catching an error that exists and then just throwing that same error. If you're not modifying it all, you just throw the error without even creating a new error, but we'll get to that in a minute. So inside of this this class instance, inside of this bundle here is a few things. There's a name. The default is capital e error.
Scott Tolinski
There's a message. That message is the message that was written when the error was thrown. So you could think of this being like, user not found, unauthorized, or just simply something failed here or there, whatever.
Scott Tolinski
These types of things could get thrown inside of your application.
Scott Tolinski
And then there's the stack.
Wes Bos
Wes, do you wanna explain what the stack is? Yeah. The stack is a stack trace leading up sort of a treasure trail for where it went wrong, and it will show you essentially what function called what function, what called what function, and it will show you which files and line numbers they were actually thrown on. That can be very helpful because sometimes your stack trace is going to be is gonna show you that the error went wrong either in, like, a Node module or in a a a module library, or it's gonna show you that it, like, happened, like, deep within the internals of v eight or Node. Js, which is not that helpful. But if you can sort of back it up Vercel levels and and read the stack trace, then you can see, okay. It happened in my code. You know, the stuff that I can control, it happened at this point, and you can kinda take it from there.
Scott Tolinski
Yeah. And and I found, personally, this to be a situation where AI can actually really help you. Because sometimes the stack trace can get a little bit ugly, or it's not clear where exactly the error is take like, actually taking place. Because the error can originate or end up somewhere, and and, like, the actual bug or, you know, whatever in your code might not necessarily be super obvious even even if you have, like, minified code or any of that stuff. Like you had mentioned, the the error could take place on line one character, you know, 2,000,000
Wes Bos
or something like that. The minified those errors are the absolute worst you have to debug. And when there's, like, no source maps available or the source maps aren't working and, like, I I feel sorry for anyone who has to spend their days. I know a lot of the folks at Century Yeah. Have to deal with this. But, man, try having to, like, figure out these obtuse source map errors that are just, like, not pointing to the wrong right part is is really tricky.
Scott Tolinski
Yeah. So I found that you can oftentimes if you are having a hard time understanding your stack trace, you can just copy and paste that whole thing, throw it into any AI of your choice and say, what's the deal here? What's going on? Hey.
Scott Tolinski
Throw me a bone. Throw me a freaking bone here. Yeah. Let me, let me know what's going on. And, I found it to be very ESLint at being able to tell me in plain English oftentimes, which is probably one of the reasons why Century has been adding, you know, AI features into their their application because it's good at that kind of stuff. It's parsing a lot of information.
Scott Tolinski
There's also a handful of node system specific errors, but we don't need to get into them too much, like code.
Scott Tolinski
Sometimes see those as error, Node, e n t, if you're dealing with the file system.
Scott Tolinski
There's syscall, path, Wes. These are types of things that you may see frequently in Node apps if you're working with FS or any of the, given Node, system packages.
Wes Bos
One more thing is is when you're throwing an error or or when errors are thrown, generally, the message is going to be a string or it's going to be something that can be parsed into a string, but the message itself can be it it Sanity be several types. Right? You could you can throw an object in there as as well. If you are creating a custom error, so you use a class, like validation error extends error, you can override the TypeScript property on that class, and that will when the two string property gets called on that error because they warp to display a string version of the message, then you can, implement your own logic there as to to how to display that. Yeah.
Wes Bos
Throwing errors. Let's talk about it. So you when you're writing your logic in your your JavaScript, you may want to throw an error versus have to handle it directly in that function. So if you Yarn, writing logic and you say, I don't necessarily care how this error is handle handled because I am simply doing some validation or doing a database lookup.
Wes Bos
If anything goes wrong at any point, I am simply just going to throw. I'm going to throw an error. You can pass along the message of that error and any other additional details that may be helpful in that error. And then at a generally, at a higher level, you're going to then go ahead and and catch that error and decide how it happens. So sometimes it makes more sense to just handle it right away inside of your application.
Wes Bos
But if you're not at a layer of your application, especially with, like, library code, I don't necessarily know how, the user of this library wants to deal with something going wrong. So, therefore, I am simply going to throw, and you have to figure it out at a different point.
Scott Tolinski
Yeah. And sometimes, you know, if you're dealing with, like, library code that fails in the library code, you call a method, you call a function or something, and that fails. Mhmm. The error might not always be something you want to continue to to throw up.
Scott Tolinski
So, like, you could catch the error from, a library method or function and then create a new error based on something that you, would rather handle in a specific way. Like, for instance, like, insert failed or something like that rather than something that has more context.
Scott Tolinski
Because you can certainly then log that error in a way that makes sense for, you know, error handlers or, you know, logging software like Century or something to handle that, like like, actually give you the insight to that information. But the application might not the rest of the application might not need to know about the exact specific cause.
Wes Bos
Yeah. And there's many cases in your logic where some errors Yarn to be expected and you do want to continue.
Wes Bos
Like, for example, a unique constraint on a database.
Wes Bos
If you're trying to save, like, an account and that email is already existing in the database, then you may wanna just catch that and then, oh, that already exists. Let me look it up and and continue on. I probably would look it up first, but that's kinda besides the point. Right? You may say, okay. That that error, we can we can handle, in a specific way, and we can continue on. While others Wes it's like, I don't know, database out of room or simply cannot connect to it, then then you're in a little bit more trouble, and you need to abandon all ship and and send something back to the user. Yeah. You could think about it like
Scott Tolinski
someone's throwing me a ball. I catch it. Yep. I can either then throw that ball again, or maybe I can take that ball and put it in a bucket and handle it later or just drop it on the ground and pretend it didn't happen. Or providing like, if you are providing
Wes Bos
a additional message to it or you're, like, trying to rephrase it, it is helpful to pass the cause property to your error. And what that will do is it will not gum up your stack trace.
Wes Bos
Mean that if you're if you're catching it and simply throwing it again, passing the original error to the cause property of your your error will make sure that your stack traces stay intact and you're not accidentally losing any information. Word. So okay. We've talked a lot about throwing here, but and we've kind of alluded directly to promises,
Scott Tolinski
and we're using a lot of the language like catch. And and so, typically, one of the ways that you're interacting with errors is via promises in your app, whether that is through a try catch block or a a dot catch on a promise, that will then be called the moment that an error has happened. So, typically, when we are trying to catch an error, you want to wrap your code, especially if there's a promise involved, in a try catch because that allows you to say, like, alright. In this block of code, I I got my hands up ready to Yeah. Ready to catch it in case this thing, starts throwing. So and then you can handle that how how you may. Exact and the other benefit of a try catch block is that you can put you can put a lot of logic inside of a try,
Wes Bos
and then you can put the catch below it and say, if any of these things, you know, if any of these things were to go wrong, you don't have to handle every single one individually, then you can go ahead and and catch it. The the alternative to that is you can chain a dot catch onto it. So even if you're using async await, I'd like to call this the mix and match, where you can say, like, const user equals await get user, but then you can also just tack a dot catch onto the end of that asynchronous function, or that promise based function.
Wes Bos
Now both the try catch and the dot catch are they have their own use cases, where they may be useful, But sometimes both of those can gum up your flow control quite a bit or to a point where, it both of them will scope the error inside of either inside of a function or inside of a block, and then it can be hard to return from a dot catch. Mhmm. It's it's hard to return from the parent. You can't return from the parent function. Right? And then a try catch is Node you have your errors in your your code and all of your variables scoped to the the curly bracket scope.
Wes Bos
So one way that I like to do is use a package called awaited two, and I've also written this one many times. And, essentially, what it does is it will it's a function that wraps your promises and will return to you a tuple, meaning an array of two pieces of data, the first piece being an error, the second piece being the actual data.
Wes Bos
And that's really nice because then you can have both your error and your successful return data available at the same level Mhmm. Without any weird scoping thing. So that's my, like, favorite way. There's been a couple proposals in JavaScript to add this natively, and I sure hope that we have it.
Scott Tolinski
Yeah. I I personally I like that flow a lot. It makes a lot of it makes too much sense, honestly, to be able to have your error and everything at the same level. There there's also something that's not explicitly related to errors, but I feel like I should mention it because I don't know if a lot of people end up actually using this, because we always see the try catch. But there's also both there's also a finally too. So there's a finally block you can do after the catch or a dot finally as well off of, just a a normal promise. But this runs after a successful or an error. So, basically,
Wes Bos
the the the catch has happened or the catch has not been triggered, but this will then always run no matter what after error. Of if it was successful or not. That can be really handy for, like, teardown. You wanna remove event listeners or Yes. Regardless of of what happened. Sometimes, like, you may ex something might error. Like, a a very common one would be if you're trying to report some data to a analytics Vercel service. Right? There's there's a high probability that the user will have an ad blocker on, and that fetch or that that post request is going to fail.
Wes Bos
And if you if you know, it's it's half of these are gonna fail anyways, it can be helpful just to stick that final logic in your finally so that you know it's regardless of what happens, I'm gonna display this to the user.
Scott Tolinski
Yes. Totally.
Wes Bos
We also have promise dot try, which is relatively new. And if you are writing a bunch of, like, promise based code and you have a function that you don't necessarily know if it is promise or not or if you simply just want to maintain the same syntax for everything, wrapping your function in a promise dot try will allow you to handle your errors as if it were a promise or not. So if you're chaining a whole bunch of stuff and somewhere in that chain, you have a, synchronous function that is not returning a promise, you can kinda fake it into a promise with by wrapping it in a promise dot try. Yeah.
Scott Tolinski
We also mentioned this already briefly. But in this scenario where you are, like, awaiting something or you're inside of a try catch block, when you catch that error, sometimes it makes sense to just rethrow it. And to rethrow it, you don't need to create a new error or anything. You just say throw and then the error that comes in from the catch. So you don't have to create a new one.
Scott Tolinski
You will see this code a lot where people are catching the error and then throwing a new error that has not been modified at all. You don't need to do that. You just throw the error.
Scott Tolinski
If you do need to add additional context, then it makes sense to create a new error from that error, and then you can just pass the current error in. You can give it a cause maybe about whatever additional context you're trying to give it. But, yes, you do not need to to create a new error if you're catching and just continue it down the line. Mhmm. Let's talk about client side errors.
Wes Bos
You may want to catch errors at different levels depending on what it is you're doing. Especially a client side, you you may be thinking about, I wanna catch these out of UI level where I can display them. Right? You may have, form submission, validation errors, instant feedback that you wanna display to your user.
Wes Bos
So, generally, you'll put those as as close as possible to the UI where where it's happening.
Wes Bos
But at other levels, you simply just wanna have, like, a a site wide error that you wanna wanna display. Right? So back in the olden days before Mhmm. React and whatnot, we had this idea of, like, flash messages, which you would just you would throw a flash message on the session. And then the next time a page loaded, that error would show up, and that was really helpful for, like, your password has been reset successfully or sorry. I I can't delete that item because you don't have have access to it. Now those have been replaced mostly with Toast errors, which can be really helpful, that little pop up in the bottom right hand corner. Those are really nice because you don't always have a good UI for displaying pnpm error, but throwing it in a pop up's always an option. Right? Yeah. Yeah. No. Totally.
Scott Tolinski
It's important to know, like, when to use certain types of errors. Right? Because oftentimes, like a toast message or a pop up or any of those things, those things are, like, good for errors that you kinda just want to alert the user of that will be gone in a moment. Right? Like or maybe you give them an x and has a timer, like, you know, try again or something. Right? But then there's also, like, inline errors, like, when you're when you're working in a form. And the reason why you would most likely rather use a ESLint error when you're working in in a form is that it provides contextual information and instant feedback to the user. Right? Where, like, if if I if I submitted my password and I expected it to work and I look away from my phone because I'm have ADHD and I get distracted, and I look back and it didn't submit, I would not know what would happen if you were using a Toast message because they're usually ephemeral. Well, that happens to me a lot. Yeah. Or it it goes away, and I I wasn't looking or, like, I said, it falls on the screen. Yeah. Yeah. That drives me nuts. Drives me nuts. So in those types of instances, it makes way more sense to put that in line contextually.
Scott Tolinski
So that way Wes your user looks at it, it shows you. I had an issue.
Scott Tolinski
I had a contextual in line error the other day, Wes, on a just one of those cheap smart home apps.
Scott Tolinski
I got, like, a smart IR blaster.
Scott Tolinski
And, man, it would not let me create an account. It was like, you know, you get all the it says, here's the things you gotta do. Got I I got all the check Bos. All the check boxes are green. I use one password to generate a password. I click go, and it says the error message pops up, and it's just password is not valid. What do you mean my password? I I could not be more valid. And I tried these several different ways, could not get past it. I'm sure it was probably
Wes Bos
some kind of error on their side. Oh, that's that's a really frustrating part is that the what might have happened there is that the their server code Wes. Simply just wrapped the whole route in, like, a try catch. And they're like, well, we should probably wrap this whole thing. I think we've covered all of our bases, but just in case and then they throw some sort of, like, generic error or or something that is misleading, and we'll say, like, password cannot be created. And that's really frustrating because you have no idea about what went wrong in that case. Or in in some cases, what's happening, and maybe I'll talk about this right now, is that if you are trying to transform server errors into client errors, you often have to, like, translate them because you don't necessarily wanna send, like, your your database thing. You may have stack traces in there that that are are sensitive. You may have, like, an actual error message that is sensitive, and those should not be actually displayed to your end user.
Wes Bos
So often, what you'll have to do is you'll have to, like, have, like, a database lookup or, like, like not a not database lookup, but, like, a map lookup. Meaning that, like, these are the possible errors that I know of, and here are the friendly texts that I can do. And often, those are translated into multiple languages as well. But then if there is something that pops up that is not expected, you'll often fall back to, like, a a very generic error message that gets displayed to the user, which is so frustrating to get. Yeah. Error messages you do not want to,
Scott Tolinski
give your users are like, email exists, wrong password, or something to indicate if the user actually has an account there.
Scott Tolinski
Or, like yeah. You you don't wanna give, people anything that they could then use to turn that information and use it to attack user accounts or or try to hack into somebody. You want that you want, typically, like yeah. The the helpful messages for authentication and stuff like that would be something like password invalid, but not like account already exists because that is a security issue.
Wes Bos
Yes. And that that's why sometimes when you get an error, you'll get, like, a reference ID as well, because sometimes, though, they're trying to protect bad people from using those errors to know what what is actually happening.
Wes Bos
But then you also if somebody were to email you that that is legitimate, you need to be able to translate that, like, obtuse error that they got to actually help them out. So that's why sometimes you'll get, like, a reference, like, a hex value or something weird in there or a unique value where they can just go ahead and look up what actually happened and then then help you from there.
Wes Bos
Yeah. Error boundaries.
Wes Bos
This is something that many React has it.
Wes Bos
Svelte is getting it or Svelte does have it now, I believe.
Wes Bos
Data boundaries. Yeah. This is the idea that in your UI, you can write a error boundary tag or component that will catch any errors that are happening inside of it. And that's really nice because you could wrap an error boundary around a component like a form and catch anything that happens inside of there.
Wes Bos
But then you can also have ones that are a little higher up that will catch values, and that's really helpful Wes, for example, you don't wanna, like, wrap your your you don't want your navigation to break if something, like, small happens on on your website. You don't want the whole website to break. So you'll often have several levels of error boundaries in your application that will try and catch anything that that bubbles up.
Wes Bos
And that's really nice because you can also with an error boundary, you can simply just throw, like, you don't care inside of a component, and you knowing that somewhere higher in the the component tree is going to successfully catch that and be able to display it to your user. Yeah. You ready to get into server errors? Yes. Yes. Let's talk about it. Let's talk about
Scott Tolinski
server errors.
Scott Tolinski
Again, we we've mentioned a little bit about server errors through the the course of this. But, really, again, server errors are something that you have to be careful about leaking into your your clients because sometimes that things, like we've mentioned several times, could be sensitive.
Scott Tolinski
And, as we've mentioned already, it's common to have a lookup of error types that you can send a message to the client to let them know that something is going wrong, but then we're handling it on our own, logging it or being able to fix it in the back end without exposing that to the client. So something very important to keep in mind. At JSON API, this is something that I've done quite a bit Wes I will, like, wrap
Wes Bos
all of my API routes for any possible uncut errors. So inside of each of my API routes, I may want to handle that in that specific API route. But if I don't, then I wrap every single route in a high order function, and that will then catch it and send a a JSON API error to it. Or even even further is I'll check the accept header on the Wes. And if the request is asking for JSON, then I'll return the error in JSON format. Otherwise, you can return the error in, like, an HTML format or whatever makes sense. So that that can be a helpful way. If you've ever, like, had an error on a website and you look in your dev tools and it says Sanity read angle bracket or cannot parse angle bracket, what's happening is that an error happened on the server. Your client code is assuming that JSON is coming back, but it it's not because it's it's setting some HTML back. And often, you can you can go into the network tab and look at the HTML that was returned, and it will show you what actually happened in that case. Yeah. That's an easy one to to have memorized if that's happening.
Scott Tolinski
The response is coming in as HTML, and then you're not expecting it to come back as HTML.
Scott Tolinski
Very common, especially today.
Scott Tolinski
So there's also HTTP response codes.
Scott Tolinski
So different response codes are things that you have to be able to handle on the ESLint. And having a good understanding of the response codes is something that is a foundational skill that you'll need to have. But in general, you know, the ones related to errors, 200 through two ninety nine are success codes.
Scott Tolinski
400 through four ninety nine are a client error, you know, 404.
Scott Tolinski
500 through five ninety nine are server errors. You could think of it as like an what is it? It's four four zero Node. That's unauthorized. Right? 500 is normally like something went wrong on the server. Right? And those can be handled in any sort of different ways. The exception to this is if you're using something like GraphQL, GraphQL will return a status code of 200 with, like, a message that there's an error. So it it's it's very funny how they do that, but they're like the reasoning for that is that, like, they're saying that the the response from GraphQL was success successfully took place, but that response was that there was a problem somewhere.
Wes Bos
Yes. That that's always funny. Like, successfully errored, if you are doing server validation and something went wrong in that validation, do you do you return a status code that like like, something went wrong along with the the error message? Yes.
Wes Bos
Or I I like, I think so. Right? Like, you can Yes. You can return a status code that is an error, but still return JSON or whatever format, like a React Vercel component payload that that you're looking for.
Wes Bos
Plus, like, in GraphQL world JS there's a possibility that part of your payload will have an error, and then other parts will be successful. So it's it's a wild world there, but often what that means at the end of the day is before you go ahead and as you get the the payload back, you're simply going to be checking what that payload looks like. And, hopefully, your TypeScript types are telling you that you have a tuple or or something like that of either an error or data, not both.
Scott Tolinski
The problem here is that people can just do anything. So that Yes. Sometimes people do the wackiest stuff. And, if it's not your code, it's good to know exactly what's going on.
Scott Tolinski
Otherwise, it's best to follow best practices.
Scott Tolinski
But what about fixing and logging these errors? This is something that, you know, JS, Sanity employees, or at least I'm a Sentry employee, we're we're able I guess you're a Sentry. Sentry shills is the correct word, Scott. Sanity shills. This is something we're very familiar with. So logging and, being able to solve these errors is something that you'll want to do in production specifically because, yeah, in development, you're you're you might be in incurring these errors, and, typically, it's happening while you're using the app, so maybe you can go find it and fix it.
Scott Tolinski
But in in production code, errors just be happening, and you might not know about it, because you might not encounter every use case in development. So the fact that things could be happening without you knowing it involves, well, potentially, users just not using your stuff because it's not working. And you might be using it yourself and be like, it's working for me. Next thing you know, you you're like, oh, wait. I have a special flag on my account specifically, or I have some logic that targets my my account specifically or not another users or whatever. There's there's some mismatch there. So being able to handle and store and log these errors is something that I think is very important.
Scott Tolinski
Obviously, I'm going to say, but I truly believe because we used Century before we were sponsored by them, before this podcast was presented by Century, like, way back when, I've been using Century forever because it it makes so much sense to log and store these errors, and it's only gotten better. So they handle logging and storing the errors, telling you how many times they've happened, how many users or which user they happen to, what browser, what version of your application, and it makes it makes fixing these things way easier. Because let's say a a bug showed up 100 times in a specific version of your app and somehow got fixed without you even knowing it, you would be able to see, oh, this isn't something I need to investigate right now. They also just, like, today announced logging generally in Century ESLint is in open beta.
Scott Tolinski
So logging is basically anytime you do any type of log, it's being stored. And there's a lot of other services that do logging, whether it's like paper trail or any of these things. And they just basically say, if your console logging or console airing anything, I'm just gonna collect all those logs, and I'm gonna give you an interface to be able to find and search for specific logs to be able to determine what happened. But with Sentry, it's kinda cool because again, this sounds like an ad.
Scott Tolinski
Is I genuinely think this is cool. They can attach it directly to your spans and errors to be like, contextually,
Wes Bos
this error and this log are related to each other. This explicit one. You can you can when an error happened to a specific user Yes. You can look at what was what your logs on the server were doing. You don't have to, like, piece those things together, which can can be really helpful.
Wes Bos
Big fan of that because, like, obviously, I think you should be able to solve a lot of your problems with just the regular issues in something like Sanity.
Wes Bos
But every now and then, you you simply just need logs or you need to be able to, like, look up your logs and see how often something happens. So I'm actually excited about having that.
Scott Tolinski
Yeah. If you're putting on on a scale of, like, what's most important to least important, I think logging and capturing errors specifically is Yep. Is the most important, and, like, logging is less important. But when they when they're contextual and and there's more information, they become I think logging becomes more useful, which not more useful than capturing errors, but, like, more useful than if it's just a big old dump all the logs.
Wes Bos
We should also say there's, like, kind of, like, two different ways to, like, log an error. Like, sometimes you may you may catch an error, and you, like, you you don't wanna log that because you've you successfully caught it and you successfully dealt with it.
Wes Bos
And and sometimes you may you may catch an error and go, oh, that that shouldn't this should never happen. Like, if you ever have code where you have this should never happen or or whatever, that's the point where I still send it off to Century. Because I'm like, I know this should never happen, but I'm gonna go send it off. Because if it does, I'm certainly gonna need to know what happened, in this use case. So never write code where you don't think an error should happen. I'll I'll tell you that because I've I've had my course platform crash several times where there was simple things where I just expected that to never happen. Like, Node example was I expected my email SMTP to never be down, or I didn't I didn't account for that possibly being an issue. Right? It just pings the API and and sent it. But if it if if it can't do that, then it was it was interfering with some of the other logic that needed to happen. So in that case, I had to catch that specific error and then throw it into a queue to to retry at a different point.
Scott Tolinski
Yeah. Yeah. Totally.
Scott Tolinski
I will say, having a tool, whatever that tool may be, does not have to be Sentry to capture these errors, I do think goes a long way for your, not and I just think it goes a long way. You know? Your users probably aren't gonna be aware of this either way. You wanna make sure your users are handled carefully, but it does, like the worst possible thing is for you your app to be causing numerous issues for several users and for you not to be aware of it. Yeah. You have no idea.
Scott Tolinski
Yeah. You have no idea. In fact, I do I was playing a game, Clair Obscure Expedition 33. Fantastic game. I've been playing it for a bit, and, I've recently found out they are a customer of centuries.
Scott Tolinski
And my game crashed last night, and I was just like, alright. They're gonna be they're gonna fix this. Whatever this is, they'll fix it, and and I'll move on from this crash, but they got that crash. I I'm very confident they got that crash.
Wes Bos
Alright. Well, we'll talk real quick about Node about TypeScript errors or errors in TypeScript, not necessarily, like like the the errors when you hover over top of something that is broken in TypeScript. But when you are catching your errors in TypeScript and you want to go ahead and use them, those errors are going to be typed as unknown by default because the reality is that TypeScript has no idea what the shape of that is going to be. There is no way to type the type of a thrown error, in TypeScript, meaning that you cannot say, JS doc, you can, but you cannot say this function throws an error of this type, if it were to go. I I kinda really want that. But if that happens, the errors are unknown by default. Meaning that before you go ahead and use them, you need to check for the type of it. You need to do a little bit of narrowing. Maybe you'll have a type predicate function that will first check if it is an instance of an error or instance of your custom error. And then once you have that, you'll be able to then go ahead and work with it, you know, display a specific message or or like I said, you can do you can do whatever you want with the errors, but you gotta first check what there is, which is sometimes very frustrating inside of TypeScript. But believe me, I've hit many instances where I assumed something would be of a specific type because I can't imagine fathom why it would ever look like that. But Mhmm.
Wes Bos
These things happen, and it's good to have the those things in place that you can check for them. These things do happen. That's just how it goes.
Scott Tolinski
Cool. Well, anything else on errors from your end?
Wes Bos
I think that's it.
Wes Bos
Let us know your tips on on how to handle errors or bridge also, like, your design patterns as to, like, where how do you throw, where do you throw, how do you display them. I think that's also really useful because I've certainly been in lots of applications where there's no, like, structure to how to handle them. It's just a bit of a mishmash, and that can be a bit a bit of a problem as well where, there's no nice way to do it, and and the UI is all all gunked up.
Scott Tolinski
Yeah. Yeah. Alright. Cool. Well, I I don't got anything else. Thank you so much for watching.
Scott Tolinski
I'm I'm curious, like you said, strategies, all that kind of stuff. So leave a comment below, and just let us know what you what you're doing.