Achieve error differentiation in Promises Background

I have a REST API using MongoDB, Node.js and Express that makes a request to my NoSQL DB and depending on different results, I want to differentiate which error I send the customer.

Problem

The current version of my code has a generic error handler and always sends the same error message to the client:

api.post("/Surveys/", (req, res) =&gt; {
        const surveyJSON = req.body;
        const sender = replyFactory(res);

        Survey.findOne({_id: surveyJSON.id})
            .then(doc =&gt; {
                if(doc !== null)
                    throw {reason: "ObjectRepeated"};

                //do stuff
                return new Survey(surveyJSON).save();
            })
            .then(() =&gt; sender.replySuccess("Object saved with success!")) 
            .catch(error =&gt; {
                /*
                 * Here I don't know if:
                 * 1. The object is repeated
                 * 2. There was an error while saving (eg. validation failed)
                 * 3. Server had a hiccup (500)
                 */
                sender.replyBadRequest(error);    
            });
    });


This is a problem, because the client will always get the same error message, no matter what and I need error differentiation!

Research

I found a possible solution, based on the division of logic and error/response handling:


https://stackoverflow.com/questions/26076511/handling-multiple-catches-in-promise-chain


However, I don't understand a few things:


I don't see how, at least in my example, I can separate the logic from the response. The response will depend on the logic after all!
I would like to avoid error sub-classing and hierarchy. First because I don't use bluebird, and I can't subclass the error class the answer suggests, and second because I don't want my code with a billion different error classes with brittle hierarchies that will change in the future.


My idea, that I don't really like either

With this structure, if I want error differentiation, the only thing I can do is to detect an error occurred, build an object with that information and then throw it:

.then(doc =&gt; {
    if(doc === null)
        throw {reason: "ObjectNotFound"};

    //do stuff
    return doc.save();
})
.catch(error =&gt; {
    if(error.reason === "ObjectNotFound")  
        sendJsonResponse(res, 404, err);
    else if(error.reason === "Something else ")
        sendJsonResponse(/*you get the idea*/);
    else //if we don't know the reasons, its because the server likely crashed
        sendJsonResponse(res, 500, err);
});


I personally don't find this solution particularly attractive because it means I will have a huge if then else chain of statements in my catch block.

Also, as mentioned in the previous post, generic error handlers are usually frowned upon (and for a good reason imo).

Questions

How can I improve this code?
Would it help to rewrite it along the lines of:

function notFoundErrorHandler(error) {
  if(error.reason === "ObjectNotFound")  
      return {code: 404, error:err);
}
function someOtherErrorHandler(error) {
  if(error.reason === something else")  
      return {code: 499, error:err);
}
function serverErrorHandler(error) {
  // No if because this is a catch all
  return {code: 500, error:err);
}

let handlers = [notFoundErrorHandler,
                someOtherErrorHandler,
                serverErrorHandler     ];

Survey.findOne({_id: surveyJSON.id})
  ...
  .catch(error =&gt; {
    respondToError(error, handlers);
  } );

function respondToError(error, handlers) {
  for (let handler of handlers) {
    let {code, error} = handler(error);
    if (code) {
       sendJsonResponse(res, code, error);
       return;
    }
  }
  console.error("Shouldn't get here");
}