Jonas: In this video, we're gonna implement some logic
in order to send different error messages
for the development and production environment.
So right now, we're sending this same response message here
basically to everyone, no matter if we're in development
or in production.
But the idea is that in production, we want to leak
as little information about our errors
to the client as possible.
So in that case, we only want to send
a nice, human-friendly message
so that the user knows what's wrong.
On the other hand, when written development,
we want to get as much information about the error
that occurred as possible, and we want that
right in the error message that's coming back.
So we could log that information also to the console,
but I think it's way more useful to have that information
right in postman, in this case.
So, we already know how to distinguish between
the development and the production environment.
And so, let's do that.
So if
process.env.node_env
is equal to development
then we want to send one type of error
and if we're in production,
then we want to send a simpler error.
Alright.
So equal to production.
Alright, so let's grab this one,
so again, when written development,
we want to get all the information that we can.
So that's also print or respond with the error stack here.
So err.stack, and then let's also print
the entire error also.
Let's say error, and set it to up okay.
Then on the other hand,
let's now copy this again.
When we're in production, we don't want the stack
and we also don't want the complete error.
So really just the status and the message.
This here looks kind of messy,
so let's export these into their own functions
and also because we're actually gonna add a lot more code
down here, in this else branch.
It's a bit cleaner to have these into
their own separate functions.
So let's say const
send error for dev
and that function should then receive the error,
and we also need to pass in the response subject.
That is because that's how we can actually
send the response, right?
So we need the response subject in order to be able to
run this code.
Here we're just gonna call
send error dev
with the error,
and the response.
Then down here,
we're gonna have
send error
production,
the same arguments.
And then here, the same.
So that was easy, let's now take it to the next level
and talk about operational errors again.
For that, let me open up the app error class
that we created, and let's remember that we mark
all the errors that we create,
using AppError is operational set to true.
So all the errors that we create ourselves
will basically be operational errors.
In fact, it's only these operational errors
for which we want to send the error message
down to the client.
At least in production.
So when we, on the other hand, have a programming error,
or some other unknown error that comes,
for example, from a third party package,
we do not want to send any error message about that
to the client in production.
And so that's no use.
This is operational property here in our error controller.
Remember how I already talked about doing that
by the time that we created this class, right?
Let's now come here to send error production
and do that test.
If error.isOperational
only in that case we actually want to send this error here.
In all the other cases,
we are simply gonna send
a very generic error message to the client.
So let's say, res.status
and we're simply gonna send a generic 500 code
and then json.
The status will be error.
Then let's just send a generic message, saying
something
went very wrong.
So doing something like this is very standard procedure.
Let me actually comment out some of the code here.
So this is an operational error that we trust.
Here we want to send a message to the client.
But in this case here,
we have an unknown error,
and so we don't want to leak the details to the client.
So we're just gonna send this message then to the client,
and also for ourselves.
For us developers, we want to know
that this kind of weird, unexpected, unknown error
occurred and we're actually gonna log it to the console.
We'll first log the error,
and then send a generic message.
Let's just say, console.error,
so this is a bit like console.log,
but it's really specific for errors
and I believe the output will then look a bit different.
So error, let's add some emoji here to make it visible
in our logs,
and then log the error as well.
Now there are real logging libraries on mpm,
that we could use here
instead of just having this simple console.error,
but just logging the error to the console
will make it visible in the logs
on the hosting platform that you're using.
I think that for now, in this kind of simple application,
that is enough.
For example, we're gonna use Heroku
by the end of the course to deploy our application.
Then when an error like this occurs,
it will be logged to the console.
In the Heroku platform, we then have access to these logs.
We can keep looking at these logs, and then in there
we're gonna find these unexpected errors
so that we can then fix them.
Right now, we're actually already building
kind of sophisticated and real-world
error-handling mechanism here.
So let's quickly recap what we just did here.
We're distinguishing between errors in development
and in production.
When we're in production, we send the error
using this function here,
which will then send as many details as possible
to the client,
so that we really get all the information
in order to get rid of the bug.
If it's a programming error,
or if it's an operational error,
then we still really want to see anything that's going on.
When we're in production,
which is arguably the most important part
of our application, then we distinguish
between operational errors,
so errors that we know and trust,
and to other errors, that might be kind of unexpected.
If the error is operational, so for example the user
tried to access a route that doesn't exist,
or tried to input invalid data,
all of these are operational errors.
Then we can send appropriate error messages,
for the client to know what went wrong.
On the other hand, we have these unknown errors,
or unexpected errors, and in that case,
we very simply say, something went wrong.
Then log the error also to our console,
so that we know that it happened and can then fix it.
Now in order for this to work,
there is something really, really important
that we need to do.
Right now there are errors that are, for example,
coming from MongoDB, which we do not mark as operational.
In this case, they would right now simply be handled
using this generic error message here.
For example, a validation error.
Right now, that's an error that's coming from MongoDB
and not from our own app error class.
We do not create these errors by ourselves.
Again, they are right now not marked as operational,
but we of course need to mark them as operational
so that we can then send the appropriate error message
back to the client.
In the example that I was just mentioning,
that the input data is invalid.
There are two or three other errors that we need to mark
as operational ourselves.
So we will do that
down here.
So in this else block,
we will do that over the next couple of lectures.