Why should I always make my Exceptions serializable? .NET
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
The short answer is that you should not treat "always make exceptions serializable" as a timeless universal rule for every modern .NET application. It was a much stronger convention in .NET Framework-era code because exceptions could cross app-domain, remoting, or other serialization boundaries. In modern .NET, the requirement is narrower, but there are still cases where serializable custom exceptions remain useful for compatibility and framework consistency.
Why the rule existed in the first place
Historically, .NET exceptions were commonly expected to support serialization because exceptions might need to cross process, remoting, or application-domain boundaries. Built-in framework exceptions followed that pattern, and custom exceptions were encouraged to do the same so they behaved like first-class .NET exceptions.
That is why older guidance often included:
- mark the exception with
[Serializable] - implement the serialization constructor
- override
GetObjectDatawhen you have extra state
In that environment, the rule made practical sense.
Why the rule is weaker in modern .NET
In modern .NET applications, especially simple ASP.NET Core services, console apps, and many internal systems, exceptions are often logged, translated to error responses, or handled locally rather than serialized across framework remoting boundaries.
That means the old blanket recommendation is less compelling for every codebase.
So the better question is not "should I always do it" but "will this exception type ever need serialization compatibility, framework parity, or reusable library correctness across boundaries?"
When serializable exceptions still make sense
It is still reasonable when:
- you are writing a reusable library and want to match established .NET exception conventions
- the exception carries custom state that may need to survive serialization scenarios
- your application still uses frameworks or infrastructure where exception serialization matters
- you want compatibility with analyzers, legacy consumers, or framework expectations
In those cases, supporting serialization keeps the custom exception aligned with the broader .NET exception model.
A typical custom exception shape
This is the classic shape. If the exception adds custom fields, those fields must also participate in serialization correctly.
When you may decide not to bother
If the exception is purely internal to one modern service and will never cross any serialization boundary, you may reasonably decide not to implement the older serialization pattern. That can be a pragmatic choice, especially if the application does not rely on legacy serialization behavior.
The key is to make the decision consciously rather than copying an old rule without context.
Be careful with custom state
If your exception has extra properties and you do choose to support serialization, then partial implementation is worse than none. In that case you must preserve the added state properly, or consumers may get an exception object that round-trips incorrectly.
That is the scenario where serialization support stops being ceremonial and starts becoming real correctness work.
The deeper rule is API quality, not ritual
For public libraries, exception design should be deliberate:
- meaningful type name
- standard constructors
- sensible inheritance
- optional serialization support when required by the intended usage
Serialization is one part of that design, not the whole story.
Common Pitfalls
- Treating old .NET Framework guidance as if it were identical for every modern .NET application.
- Adding serialization ceremony to every internal exception type without knowing why.
- Implementing
[Serializable]but forgetting to preserve custom exception state correctly. - Omitting standard exception constructors in a public exception type.
- Assuming "not always required" means exception design no longer matters.
Summary
- Serializable custom exceptions were historically important in .NET because exceptions often crossed serialization boundaries.
- In modern .NET, the old blanket rule is less universal.
- Serialization still makes sense for reusable libraries, compatibility, and exceptions with meaningful boundary-crossing requirements.
- If you support it, implement it correctly rather than half-doing it.
- Make the choice based on your application's actual exception-transport and library-design needs, not on an unexamined slogan.

