When to use Custom Exceptions?

When to use Custom Exceptions?


A conversation I recently had on the DDD-CQRS-ES slack channel got me thinking about custom exceptions and when to use them. Up until this point I’ve always considered it best practice to define custom exception instead of using the the standard exceptions supplied

Read More

Custom exceptions get a bad reputation because they are often used as control flow, thrown to signal every foreseeable branch in a program. The better question is whether a caller can genuinely do something different when a failure occurs. If the answer is no, a plain standard exception usually says everything that needs saying, and the extra type only adds noise to the call stack.

At the same time, domain code often benefits from exception types that carry meaning. When a rule is broken inside a domain model, a named exception tells the story far better than a generic one, and it lets the surrounding application layer decide whether to translate it into a result, a rejection message, or a log entry. The type becomes a small piece of the public vocabulary of the system.

Rarely, an exception should be caught and handled in exactly one place. That is a good sign it deserves its own type, because the handler is the real consumer and the throw site is only the producer. In practice this shows up around boundaries such as persistence, messaging, or third-party integrations, where a failure means something specific and recovery has a specific shape.

The gang of behavioural patterns includes several ways to model failure without throwing at all. Result objects, option wrappers, and validation pipelines make the unhappy path visible in the signature of a method, and they remove the surprise of a mid-flight exception that nobody documented. Choosing not to throw is often the cleaner design, particularly deep inside a domain where the state was already checked.

Talking about this at conferences and on community channels is part of the job. A hallway conversation about custom exceptions can turn into a recorded session on patterns and practice, and the value comes from the disagreement as much as the conclusion. People arrive with different backgrounds and defend different defaults, which is exactly why the topic keeps resurfacing.

The same instinct applies to code review. A pull request that introduces a broad catch block or a new exception hierarchy deserves the same scrutiny as one that changes a database schema. Messy merges, forgotten constructors, and unnecessary abstractions rarely arrive alone, and a careful read of the failure handling often reveals where the design is still unclear.

Versioning matters too. A public exception type is a contract, and changing its name or its constructor signature breaks every caller that catches it. Keeping them minimal, immutable, and free of UI or framework dependencies means the library can evolve without forcing painful migrations on the applications that depend on it.

There is a testing angle as well. Exception types that are specific and well-named make assertions readable, because the test reads as a statement about behaviour rather than about implementation details. A suite full of generic failure assertions hides intent, and when something breaks the first time, the message is the only clue you have about what the author actually expected.

Beyond code, the personal parts of a developer's life shape how all this thinking happens. Climbing and surfing in cold water demand a kind of attention to failure and recovery that mirrors careful software design: prepare, commit, and know when the conditions are against you. Conversation is the bridge between the two, and writing is how the ideas survive long enough to be useful to someone else.

Command Handlers

Command Handlers


The command pattern is one of the patterns defined in the gang of four’s behavioural patterns but I rarely see it get much use. The idea behind the pattern is to encapsulate all of the information required to execute an action within a

Read More
DevDay Omnisharp Talk

DevDay Omnisharp Talk


Here’s the recording of my session about Omnisharp that I gave at DevDay in Poland. The audience were great and I can honestly say it is one of the best conferences I’ve been to. So thanks to Rafał and Michał for having me.

Read More

Keeping a clean git history


Is it just me? I can’t stand a messy git history. Full of unnecessary merges and commits. With messages such as: “Oops…” “Forgot to add a file” “Fixed a bug” Making it difficult to look back and find why and when certain changes

Read More