Search code examples
javascriptnode.jsexpressservertry-catch

Is 4xx and 5xx network errors?


I have a node server that basically reads a component from a specific path, executes the code, and returns the data to the other server.

Sometimes during the code execution of the component, I get a 403 response.

Error:

ApolloError: Response not successful: Received status code 403

I'm using .catch() to catch the 403 response but it's not helping and there are frequent pod crashes due to the 403.

I have checked this StackOverflow answer - Fetch: reject promise and catch the error if status is not OK?

It mentions that

Since 4xx and 5xx responses aren't network errors, there's nothing to catch

Is this correct?

If the above statement is true, can it be handled like the below:

app.use((req,res) => {
   res.status(403).send('');
})

Solution

  • Is 4xx and 5xx network errors?

    No, they're HTTP error responses, successfully transferred from the server to the client via the network.

    I'm using .catch() to catch the 403 response

    I assume you mean with fetch given the question you linked to. This is a common issue (a footgun in my view) with using the fetch API. fetch only rejects its promise on network errors, not HTTP errors. So, it will reject its promise if it can't contact the server. It won't if it successfully contacts the server and receives an HTTP error response.

    The answers to the question you link (such as this one) and my linked blog post above describe how to handle this using a common path for network and HTTP errors: When you first get the Response object, check its ok property and throw if it's not true, then handle rejection in a common rejection handler.

    But reiterating in case those resources disappear (unlikely, but answers are supposed to be self-contained), using JSON as an example, I'll usually have something like this in my codebase on a project:

    async function fetchJSON(...args) {
        const response = await fetch(...args);
        if (!response.ok) {
            // Network was fine, but there was an HTTP error
            throw new Error(`HTTP error ${response.status}`);
        }
        return await response.json();
    }
    

    I do that because the vast, vast, vast majority of the time, the code doing the fetch doesn't care whether there was a network error or an HTTP error, it just cares that the fetch (and associated JSON parsing) did or didn't work.