1 00:00:01,150 --> 00:00:03,353 In this video, we're gonna implement some logic 2 00:00:03,353 --> 00:00:06,390 in order to send different error messages 3 00:00:06,390 --> 00:00:09,173 for the development and production environment. 4 00:00:10,810 --> 00:00:14,490 So right now, we're sending this same response message here 5 00:00:14,490 --> 00:00:17,389 basically to everyone, no matter if we're in development 6 00:00:17,389 --> 00:00:18,920 or in production. 7 00:00:18,920 --> 00:00:21,690 But the idea is that in production, we want to leak 8 00:00:21,690 --> 00:00:23,810 as little information about our errors 9 00:00:23,810 --> 00:00:25,583 to the client as possible. 10 00:00:26,420 --> 00:00:28,490 So in that case, we only want to send 11 00:00:28,490 --> 00:00:30,340 a nice, human-friendly message 12 00:00:30,340 --> 00:00:33,070 so that the user knows what's wrong. 13 00:00:33,070 --> 00:00:34,858 On the other hand, when written development, 14 00:00:34,858 --> 00:00:37,700 we want to get as much information about the error 15 00:00:37,700 --> 00:00:40,390 that occurred as possible, and we want that 16 00:00:40,390 --> 00:00:42,950 right in the error message that's coming back. 17 00:00:42,950 --> 00:00:45,520 So we could log that information also to the console, 18 00:00:45,520 --> 00:00:48,340 but I think it's way more useful to have that information 19 00:00:48,340 --> 00:00:51,150 right in postman, in this case. 20 00:00:51,150 --> 00:00:53,660 So, we already know how to distinguish between 21 00:00:53,660 --> 00:00:56,010 the development and the production environment. 22 00:00:56,870 --> 00:00:58,213 And so, let's do that. 23 00:00:59,130 --> 00:00:59,963 So if 24 00:01:01,630 --> 00:01:05,010 process.env.node_env 25 00:01:06,510 --> 00:01:08,970 is equal to development 26 00:01:11,810 --> 00:01:13,780 then we want to send one type of error 27 00:01:15,530 --> 00:01:17,060 and if we're in production, 28 00:01:17,060 --> 00:01:21,020 then we want to send a simpler error. 29 00:01:21,020 --> 00:01:21,853 Alright. 30 00:01:24,290 --> 00:01:26,913 So equal to production. 31 00:01:30,160 --> 00:01:33,343 Alright, so let's grab this one, 32 00:01:34,390 --> 00:01:36,380 so again, when written development, 33 00:01:36,380 --> 00:01:39,850 we want to get all the information that we can. 34 00:01:39,850 --> 00:01:43,763 So that's also print or respond with the error stack here. 35 00:01:48,620 --> 00:01:52,300 So err.stack, and then let's also print 36 00:01:52,300 --> 00:01:54,483 the entire error also. 37 00:01:56,240 --> 00:02:00,830 Let's say error, and set it to up okay. 38 00:02:00,830 --> 00:02:02,003 Then on the other hand, 39 00:02:03,030 --> 00:02:05,183 let's now copy this again. 40 00:02:06,040 --> 00:02:09,350 When we're in production, we don't want the stack 41 00:02:09,350 --> 00:02:12,493 and we also don't want the complete error. 42 00:02:13,490 --> 00:02:16,113 So really just the status and the message. 43 00:02:19,190 --> 00:02:20,933 This here looks kind of messy, 44 00:02:21,930 --> 00:02:24,550 so let's export these into their own functions 45 00:02:24,550 --> 00:02:27,440 and also because we're actually gonna add a lot more code 46 00:02:27,440 --> 00:02:30,719 down here, in this else branch. 47 00:02:30,719 --> 00:02:33,730 It's a bit cleaner to have these into 48 00:02:33,730 --> 00:02:35,180 their own separate functions. 49 00:02:36,500 --> 00:02:37,550 So let's say const 50 00:02:39,540 --> 00:02:41,480 send error for dev 51 00:02:43,930 --> 00:02:46,470 and that function should then receive the error, 52 00:02:46,470 --> 00:02:49,903 and we also need to pass in the response subject. 53 00:02:51,990 --> 00:02:54,930 That is because that's how we can actually 54 00:02:54,930 --> 00:02:57,223 send the response, right? 55 00:02:58,360 --> 00:03:02,090 So we need the response subject in order to be able to 56 00:03:02,090 --> 00:03:02,933 run this code. 57 00:03:04,080 --> 00:03:06,510 Here we're just gonna call 58 00:03:07,410 --> 00:03:08,990 send error dev 59 00:03:09,890 --> 00:03:11,263 with the error, 60 00:03:11,263 --> 00:03:13,073 and the response. 61 00:03:14,270 --> 00:03:15,483 Then down here, 62 00:03:17,030 --> 00:03:18,030 we're gonna have 63 00:03:18,030 --> 00:03:19,850 send error 64 00:03:20,900 --> 00:03:21,783 production, 65 00:03:24,830 --> 00:03:26,253 the same arguments. 66 00:03:36,300 --> 00:03:37,500 And then here, the same. 67 00:03:43,041 --> 00:03:46,740 So that was easy, let's now take it to the next level 68 00:03:46,740 --> 00:03:49,810 and talk about operational errors again. 69 00:03:49,810 --> 00:03:53,230 For that, let me open up the app error class 70 00:03:53,230 --> 00:03:56,270 that we created, and let's remember that we mark 71 00:03:56,270 --> 00:03:57,870 all the errors that we create, 72 00:03:57,870 --> 00:04:02,313 using AppError is operational set to true. 73 00:04:03,721 --> 00:04:05,760 So all the errors that we create ourselves 74 00:04:05,760 --> 00:04:07,873 will basically be operational errors. 75 00:04:09,100 --> 00:04:11,950 In fact, it's only these operational errors 76 00:04:11,950 --> 00:04:14,540 for which we want to send the error message 77 00:04:14,540 --> 00:04:15,703 down to the client. 78 00:04:16,720 --> 00:04:18,310 At least in production. 79 00:04:18,310 --> 00:04:21,900 So when we, on the other hand, have a programming error, 80 00:04:21,900 --> 00:04:23,880 or some other unknown error that comes, 81 00:04:23,880 --> 00:04:26,500 for example, from a third party package, 82 00:04:26,500 --> 00:04:29,930 we do not want to send any error message about that 83 00:04:29,930 --> 00:04:31,864 to the client in production. 84 00:04:31,864 --> 00:04:33,470 And so that's no use. 85 00:04:33,470 --> 00:04:37,340 This is operational property here in our error controller. 86 00:04:37,340 --> 00:04:40,090 Remember how I already talked about doing that 87 00:04:40,090 --> 00:04:43,693 by the time that we created this class, right? 88 00:04:45,580 --> 00:04:48,780 Let's now come here to send error production 89 00:04:49,730 --> 00:04:50,913 and do that test. 90 00:04:52,270 --> 00:04:54,787 If error.isOperational 91 00:05:00,630 --> 00:05:05,053 only in that case we actually want to send this error here. 92 00:05:06,940 --> 00:05:08,113 In all the other cases, 93 00:05:10,070 --> 00:05:11,330 we are simply gonna send 94 00:05:11,330 --> 00:05:14,580 a very generic error message to the client. 95 00:05:14,580 --> 00:05:17,310 So let's say, res.status 96 00:05:19,400 --> 00:05:22,110 and we're simply gonna send a generic 500 code 97 00:05:23,930 --> 00:05:25,123 and then json. 98 00:05:28,120 --> 00:05:30,363 The status will be error. 99 00:05:33,230 --> 00:05:36,660 Then let's just send a generic message, saying 100 00:05:38,200 --> 00:05:39,033 something 101 00:05:41,360 --> 00:05:42,573 went very wrong. 102 00:05:43,690 --> 00:05:46,983 So doing something like this is very standard procedure. 103 00:05:48,420 --> 00:05:51,133 Let me actually comment out some of the code here. 104 00:05:54,530 --> 00:05:57,533 So this is an operational error that we trust. 105 00:06:03,700 --> 00:06:06,200 Here we want to send a message to the client. 106 00:06:06,200 --> 00:06:07,503 But in this case here, 107 00:06:16,130 --> 00:06:17,973 we have an unknown error, 108 00:06:19,080 --> 00:06:22,673 and so we don't want to leak the details to the client. 109 00:06:28,470 --> 00:06:31,380 So we're just gonna send this message then to the client, 110 00:06:31,380 --> 00:06:33,070 and also for ourselves. 111 00:06:33,070 --> 00:06:35,340 For us developers, we want to know 112 00:06:35,340 --> 00:06:38,610 that this kind of weird, unexpected, unknown error 113 00:06:38,610 --> 00:06:41,993 occurred and we're actually gonna log it to the console. 114 00:06:49,100 --> 00:06:50,593 We'll first log the error, 115 00:06:56,702 --> 00:06:59,369 and then send a generic message. 116 00:07:00,280 --> 00:07:03,270 Let's just say, console.error, 117 00:07:03,270 --> 00:07:05,490 so this is a bit like console.log, 118 00:07:05,490 --> 00:07:07,870 but it's really specific for errors 119 00:07:07,870 --> 00:07:10,670 and I believe the output will then look a bit different. 120 00:07:12,090 --> 00:07:15,670 So error, let's add some emoji here to make it visible 121 00:07:15,670 --> 00:07:16,543 in our logs, 122 00:07:17,950 --> 00:07:20,360 and then log the error as well. 123 00:07:20,360 --> 00:07:23,213 Now there are real logging libraries on mpm, 124 00:07:23,213 --> 00:07:24,550 that we could use here 125 00:07:24,550 --> 00:07:28,030 instead of just having this simple console.error, 126 00:07:28,030 --> 00:07:30,430 but just logging the error to the console 127 00:07:30,430 --> 00:07:32,220 will make it visible in the logs 128 00:07:32,220 --> 00:07:34,363 on the hosting platform that you're using. 129 00:07:35,486 --> 00:07:39,200 I think that for now, in this kind of simple application, 130 00:07:39,200 --> 00:07:40,073 that is enough. 131 00:07:41,110 --> 00:07:42,860 For example, we're gonna use Heroku 132 00:07:42,860 --> 00:07:45,710 by the end of the course to deploy our application. 133 00:07:45,710 --> 00:07:47,600 Then when an error like this occurs, 134 00:07:47,600 --> 00:07:49,970 it will be logged to the console. 135 00:07:49,970 --> 00:07:54,180 In the Heroku platform, we then have access to these logs. 136 00:07:54,180 --> 00:07:57,080 We can keep looking at these logs, and then in there 137 00:07:57,080 --> 00:07:59,220 we're gonna find these unexpected errors 138 00:07:59,220 --> 00:08:00,670 so that we can then fix them. 139 00:08:01,678 --> 00:08:04,470 Right now, we're actually already building 140 00:08:04,470 --> 00:08:07,000 kind of sophisticated and real-world 141 00:08:07,000 --> 00:08:08,713 error-handling mechanism here. 142 00:08:09,720 --> 00:08:13,240 So let's quickly recap what we just did here. 143 00:08:13,240 --> 00:08:16,380 We're distinguishing between errors in development 144 00:08:16,380 --> 00:08:17,373 and in production. 145 00:08:18,720 --> 00:08:21,420 When we're in production, we send the error 146 00:08:21,420 --> 00:08:22,970 using this function here, 147 00:08:22,970 --> 00:08:26,050 which will then send as many details as possible 148 00:08:26,050 --> 00:08:27,340 to the client, 149 00:08:27,340 --> 00:08:28,997 so that we really get all the information 150 00:08:28,997 --> 00:08:31,730 in order to get rid of the bug. 151 00:08:31,730 --> 00:08:33,332 If it's a programming error, 152 00:08:33,332 --> 00:08:35,670 or if it's an operational error, 153 00:08:35,670 --> 00:08:39,083 then we still really want to see anything that's going on. 154 00:08:40,670 --> 00:08:42,000 When we're in production, 155 00:08:42,000 --> 00:08:44,330 which is arguably the most important part 156 00:08:44,330 --> 00:08:47,090 of our application, then we distinguish 157 00:08:47,090 --> 00:08:48,590 between operational errors, 158 00:08:48,590 --> 00:08:50,950 so errors that we know and trust, 159 00:08:50,950 --> 00:08:54,163 and to other errors, that might be kind of unexpected. 160 00:08:55,660 --> 00:08:58,800 If the error is operational, so for example the user 161 00:08:58,800 --> 00:09:01,530 tried to access a route that doesn't exist, 162 00:09:01,530 --> 00:09:03,680 or tried to input invalid data, 163 00:09:03,680 --> 00:09:05,253 all of these are operational errors. 164 00:09:05,253 --> 00:09:08,130 Then we can send appropriate error messages, 165 00:09:08,130 --> 00:09:10,880 for the client to know what went wrong. 166 00:09:10,880 --> 00:09:13,820 On the other hand, we have these unknown errors, 167 00:09:13,820 --> 00:09:16,380 or unexpected errors, and in that case, 168 00:09:16,380 --> 00:09:19,420 we very simply say, something went wrong. 169 00:09:19,420 --> 00:09:21,670 Then log the error also to our console, 170 00:09:21,670 --> 00:09:24,433 so that we know that it happened and can then fix it. 171 00:09:25,510 --> 00:09:27,080 Now in order for this to work, 172 00:09:27,080 --> 00:09:29,160 there is something really, really important 173 00:09:29,160 --> 00:09:30,193 that we need to do. 174 00:09:31,040 --> 00:09:33,340 Right now there are errors that are, for example, 175 00:09:33,340 --> 00:09:37,550 coming from MongoDB, which we do not mark as operational. 176 00:09:37,550 --> 00:09:40,970 In this case, they would right now simply be handled 177 00:09:40,970 --> 00:09:43,500 using this generic error message here. 178 00:09:43,500 --> 00:09:45,330 For example, a validation error. 179 00:09:45,330 --> 00:09:48,000 Right now, that's an error that's coming from MongoDB 180 00:09:48,000 --> 00:09:51,356 and not from our own app error class. 181 00:09:51,356 --> 00:09:54,869 We do not create these errors by ourselves. 182 00:09:54,869 --> 00:09:58,800 Again, they are right now not marked as operational, 183 00:09:58,800 --> 00:10:02,130 but we of course need to mark them as operational 184 00:10:02,130 --> 00:10:04,680 so that we can then send the appropriate error message 185 00:10:04,680 --> 00:10:06,400 back to the client. 186 00:10:06,400 --> 00:10:08,360 In the example that I was just mentioning, 187 00:10:08,360 --> 00:10:10,263 that the input data is invalid. 188 00:10:11,250 --> 00:10:14,230 There are two or three other errors that we need to mark 189 00:10:14,230 --> 00:10:15,793 as operational ourselves. 190 00:10:16,930 --> 00:10:18,020 So we will do that 191 00:10:19,410 --> 00:10:20,670 down here. 192 00:10:20,670 --> 00:10:22,193 So in this else block, 193 00:10:23,400 --> 00:10:25,850 we will do that over the next couple of lectures.