You should only ever be squashing an error into a success response if that's what someone would be expecting but that's rarely the case. Normally you should be allowing the error to bubble up and be decided by the caller.
I can think of a couple cases where catching an error down low with the purpose of squashing it makes sense. One would be for a service that you know may not have data and you don't care if it doesn't. For instance, trying to get geolocation data for a user in order to improve their experience but if it fails you don't need to show an error:
Another case is when you might have multiple ways of handling the request where one is prioritized over the other. In this case, you can catch errors from the first attempt and try a second method. If they both error out, then the result promise will be an error as well.
I can think of a couple cases where catching an error down low with the purpose of squashing it makes sense. One would be for a service that you know may not have data and you don't care if it doesn't. For instance, trying to get geolocation data for a user in order to improve their experience but if it fails you don't need to show an error:
return geolocationService.fetch().catch((err) { /* log error /; return {}; / empty result/ });
Another case is when you might have multiple ways of handling the request where one is prioritized over the other. In this case, you can catch errors from the first attempt and try a second method. If they both error out, then the result promise will be an error as well.
return primary.fetch().catch((err) => { return secondary.fetch(); }).then((data) => { / manipulate data */});