Card 04/ 10

ComparisonDifficulty: Intermediate1 min

Catch It, Declare It, or Wrap It

A checked exception arrives in a method that cannot do anything useful about it. There are three legal responses, and picking by whichever makes the red squiggle go away is how a codebase ends up catching everything three frames too early.

Three responses to a checked exception, and what each says to the caller
ResponseWrittenSays to your caller
Catchtry { … } catch (IOException e) { … }I dealt with it; carry on
Declarevoid load() throws IOExceptionThis can fail your way; you decide
Wrapthrow new ConfigException("…", e)It failed, in my terms rather than the library's

The decision rule. Catch only where you can actually do something — retry, fall back to a default, tell the user. Declare when the caller is the one with the context. Wrap when the exception's type would leak an implementation detail your caller should not know about.

java
Rates load() {
    try {
        return parse(Files.readString(path));
    } catch (IOException e) {
        throw new ConfigException("cannot read rates from " + path, e);
    }
}

The second argument on line 5 is the part that matters. Passing the original exception as the cause keeps its stack trace attached, so the log shows both what your code was trying to do and which line underneath actually failed.