I'm new to programming, and my boss told me that try-catch statements are "garbage" and that I should avoid them entirely. That confused me because I thought exceptions were a standard part of error handling in many languages. I understand that they can be abused, but is there a legitimate reason to avoid them completely? When should I use try-catch, and when would explicit error values, validation, or another approach be better?
2 Answers
Your boss may be objecting to exceptions as the default control-flow mechanism rather than to error handling itself. Exceptions can create hidden control-flow paths: a function several calls down can interrupt the current code and be handled far away. They can also have performance costs when thrown frequently. Languages such as Go, Rust, and some newer APIs use explicit result or error values instead, which makes failures visible at each call site. Those approaches can be easier to reason about, but they may also be more verbose. In Java, Python, JavaScript, and similar languages, exceptions are often idiomatic or required by libraries, so avoiding them completely is not realistic. Ask your boss which language, patterns, and specific examples they have in mind; a blanket rule is much less useful than a clear team convention.
Try-catch is not inherently bad, but it is easy to misuse. It makes sense when an operation can fail at the moment it is attempted—opening a file, calling a network service, parsing external input, or using a library that reports failures through exceptions. Checking that something will probably work beforehand is not always safe because the state can change between the check and the operation. The important part is to catch specific exceptions you can actually handle, log or propagate errors meaningfully, and avoid empty catch blocks or catching everything indiscriminately. A huge catch block that contains most of the application’s logic is usually a design problem.
A particularly bad pattern is catching an exception and immediately throwing a generic replacement that loses the original message and stack trace. If you rethrow, preserve the original cause and add context only when it helps.

A good general rule is to prevent and validate expected input where practical, use result-style handling when the language and API support it, and reserve try-catch for failures that are exceptional or need to be handled at a particular boundary. Most importantly, do not silently swallow errors—fail clearly, recover deliberately, or let the error reach a suitable top-level handler.