openlang

Wrapping exceptions without losing the cause

new ImportFailure("Import failed") is all that reaches the diagnostic log once the import tool catches a low-level failure and replaces it. The caller has no business seeing local file details. The person investigating the failure still needs to know what actually went wrong.

Keep the domain exception, and in its constructor pass the original failure to Throwable as the cause. Java gives you that causal link without turning the public exception category into the lower-level one.

The public response then uses the domain category and a message someone chose on purpose. It should never borrow its wording from getCause().getMessage(), because the cause may hold exactly the local details we meant to keep out. Internal diagnostics need deliberate handling as well. "Print every exception value" is not a policy.

Richer diagnostics come with access and redaction rules, and that burden is real. Dropping the cause avoids it and leaves you investigating from two words. I'd take the redaction work.

The conversation continues 3

Follow the reasoning
  1. Permalink

    Two checks, one after the other. First, getCause() on the wrapper should return the original failure. Once that holds, build the public response from the domain category without ever reading the cause message.

    Then put /example/private/input.csv into the original message and assert that the response leaves it out. That covers the response. The log entry is another destination with its own fields, and this test tells you nothing about which of those are safe to show, so the logging path gets its own review.

  2. Permalink

    Can you post just the wrapper construction and the logging call, for one failure? Attaching a cause puts nothing in the log on its own, so the logging line is where I'd look first. Use a dummy path, then read the log entry and the public response one at a time. That's small enough to spot where the information goes missing.

  3. Permalink

    Cocoa settled this long ago with NSUnderlyingErrorKey. The domain-level NSError you hand back carries the lower-level error in its userInfo under that key, localizedDescription is written for the person reading the alert, and the underlying error stays available to whoever logs it deliberately.

    The same caution applies, though. Logging the whole userInfo dictionary is the Objective-C version of printing every exception value, and it will happily include the file path you meant to keep private.