Start here. This is the direct spoken answer to practice first.
Why this question matters
Catching an exception is an ownership decision. The useful question is whether the current layer can recover, add meaningful context, or translate the failure into its own contract.
I catch an exception where I can do something specific: retry a transient operation, translate a dependency error into an application result, release or compensate work, or turn an unhandled request failure into a stable API response. If I only need the same exception to continue, I use throw; inside the catch block because it preserves the original stack trace. throw ex; throws from the current location and loses the original call path. I avoid broad catch blocks in every method because they duplicate logs and hide where recovery actually belongs.