Hint
throw inside .then = return Promise.reject(). Errors propagate down the chain until a .catch handles them.
Promise.resolve('ok')
.then(() => { throw new Error('oops'); })
.catch(e => e.message)
.then(msg => console.log(msg));oops
Explanation: throw inside .then converts to rejected Promise. .catch handles it and returns e.message. Next .then receives "oops".
Key Insight: throw inside .then = return Promise.reject(). Errors propagate down the chain until a .catch handles them.