909: Handling and Throwing Errors

## Metadata
- Author: [[Syntax - Tasty Web Development Treats]]
- Full Title: 909: Handling and Throwing Errors
- Category: #podcasts
- URL: https://share.snipd.com/episode/6c5369b6-fcd1-4981-85e5-042de600113b
## Document Notes
## Highlights
- **Throwing and Catching Errors**
- Throwing an error means sending it out to be caught somewhere else in your code.
- Catching an error means handling it to log, display UI, or retry logic as needed.
Transcript:
Wes Bos
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, is the whole idea of like thrown and catching. So when you have an error, whether it's in your own code, whether it's in like a module that you have done, or whether it's like something that you did not totally expect, like your application Has a syntax error in it somewhere. That is the word that we use there is thrown, right? An error is thrown. And then when you want to handle that error, the word that we use there is catch. So simply like it's Scott has here, it's like throwing a ball, but it makes you sad. Something went wrong. You simply throw it. Ah, 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 going to 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. Yeah, now you're going to have a problem over there and how you handle it is up to you. But there's numerous ways of taking care of that from there. Inside of an error is 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 are throwing. So if you're simply just throwing a new error, you can just throw error. 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 point. But the new keyword is not necessary, which I had no idea. I was adding new for probably my entire career, but think of the perf I could have in the time. I could have saved without typing the new.
Scott Tolinski
By not constructing a new instance. And even if there's some thought there too, if you're catching an error that exists and then just throwing that same error, If you're not modifying that 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. 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. These types of things could get thrown inside of your application. And then there's the stack. Wes, do you want to explain what the stack is?
Wes Bos
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 going to show you that the error went wrong either in like a node module or in a a module library or it's going To show you that it like happened like deep within the internals of v8 or node.js which is not that helpful but if you can sort of back it up several levels and and read the 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 kind of take it from there. Yeah.
Scott Tolinski
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 taking like actually taking place because the error can originate or end up somewhere. And like the actual bug or, you know, whatever in your code might not necessarily be super obvious. Even if you have like minified code or any of that stuff, like you had mentioned ([Time 0:01:40](https://share.snipd.com/snip/2683ba19-2597-45c8-909c-dbea0834ac03))
- **What Errors Contain**
- Errors contain name, message, and stack trace details.
- The stack trace is a trail of function calls showing where the error occurred and is crucial for debugging.
Transcript:
Scott Tolinski
Inside of an error is 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 are throwing. So if you're simply just throwing a new error, you can just throw error. 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 point. But the new keyword is not necessary, which I had no idea. I was adding new for probably my entire career, but think of the perf I could have in the time. I could have saved without typing the new.
Scott Tolinski
By not constructing a new instance. And even if there's some thought there too, if you're catching an error that exists and then just throwing that same error, If you're not modifying that 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. 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. These types of things could get thrown inside of your application. And then there's the stack. Wes, do you want to explain what the stack is?
Wes Bos
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. ([Time 0:03:01](https://share.snipd.com/snip/c2bfa2d0-cdd4-4d45-b0a9-dcda6a9569b9))
- **Use awaited-to for Async**
- Use packages like awaited-to to handle async errors elegantly.
- This returns a tuple of [error, data] keeping error handling and data at the same scope.
Transcript:
Wes Bos
And I've also written this one many times. And essentially what it does is 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. Because then you can have both your error and your successful return data available at the same level without any weird scoping thing. ([Time 0:14:18](https://share.snipd.com/snip/56d48925-45d0-472d-aa5f-99588fcf19b0))
- **Client-side Error Handling**
- Catch client-side errors at different levels depending on UI needs.
- Use inline errors for forms to give contextual and persistent feedback to users.
Transcript:
Wes Bos
Let's talk about client side errors. You may want to catch errors at different levels, depending on what it is you're doing, especially a client side. You may be thinking about, I want to catch these out of UI level where I can display them, right? You may have form submission, validation errors, instant feedback that you want to display to your user. So generally, you'll put those as close as possible to the UI where it's happening. But at other levels, you simply just want to have a site-wide error that you want to display, right? So back in the olden days before React and whatnot, we had this idea of flash messages, which 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 can't delete that item because you don't have access to it. Now those have been replaced mostly with toast errors, which can be really helpful. The little pop up in the bottom right hand corner. ([Time 0:18:12](https://share.snipd.com/snip/6905e449-3544-4eba-960d-d562b673f375))
- **Transform Server Errors for Client**
- Transform server errors into user-friendly client messages to hide sensitive info.
- Use mappings to convert known errors into friendly, localized text.
Transcript:
Wes Bos
Or 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 translate them Because you don't necessarily want to send your database thing. You may have stack traces in there that are sensitive. You may have an actual error message that is sensitive, and those should not be actually displayed to your end user. So often what you'll have to do is you'll have to like have like a database lookup or like I'm 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. ([Time 0:21:57](https://share.snipd.com/snip/f125cc9b-c008-4cbc-94c5-39d3dafa7c2d))
- **Log and Solve Errors Efficiently**
- Use tools like Sentry to capture, log, and solve production errors effectively.
- Log unexpected errors to track issues that should never occur and fix proactively.
Transcript:
Scott Tolinski
But what about fixing and logging these errors? This is something that, you know, as a Sentry employee, or at least I'm a Sentry employee, we're able, I guess you're a Sentry employee as well. Sentry shills is the correct word, Scott. As Sentry 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 might be incurring these errors and Typically it's happening while you're using the app, so maybe you can go find it and fix it. But 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 can 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'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. 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 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 happened to what browser, what version of your application, And it makes it makes fixing these things way easier. Because let's say 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 Sentry is an open beta. 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 you're console logging or console airing anything, I'm just going to collect all those logs. And I'm going to 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 kind of cool,, again, this sounds like an ad. I genuinely think this is cool. They can attach it directly to your spans and errors to be like, contextually, this error and this log are related to each other.
Wes Bos
This explicit one. You can, when an error happened to a specific user, you can look at what your logs on the server were doing. You don't have to, piece those things together, which can be really helpful. ([Time 0:30:09](https://share.snipd.com/snip/1cc4b7a9-51ba-4dfa-8617-a159f8b46b0c))
- **Handle Errors in TypeScript Safely**
- In TypeScript, errors are typed as unknown by default and need type checking.
- Implement custom type guards to narrow error types before handling them.
Transcript:
Wes Bos
All right. Well, we'll talk real quick about TypeScript errors or errors in TypeScript. Not necessarily like 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, JSLock you can, but you cannot say this function throws an error of this type. 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, display a specific message or like I said, you can do whatever you want with the errors, but you got to first Check what there is, which is sometimes very frustrating inside of TypeScript. ([Time 0:36:16](https://share.snipd.com/snip/fe7ae464-3d7f-4d91-8349-6307c4d76ede))