Make a custom .NET Exception serializable
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
A custom .NET exception is only fully aligned with the platform conventions when it follows the standard exception pattern, including serialization support where required. The key pieces are the [Serializable] attribute, the normal exception constructors, and a serialization constructor that restores custom state. If your exception adds extra properties, you also need to write them into SerializationInfo.
The Standard Exception Pattern
At minimum, a custom exception should derive from Exception and provide the usual constructors:
This already makes the exception participate correctly in the standard serialization pattern expected by classic .NET code.
Adding Custom Properties
The real reason serialization support matters is when the exception carries extra data. Suppose the exception includes a field name and an error code:
Without the overridden GetObjectData, the extra properties would be lost during serialization and deserialization.
Why the Serialization Constructor Matters
The protected constructor that accepts SerializationInfo and StreamingContext is how .NET reconstructs the exception. It should restore the custom data that you previously stored in GetObjectData.
If you omit this constructor on a custom exception with extra properties, deserialization may fail or your custom state may come back empty. That is the main reason the full pattern exists.
When You Actually Need This
In many modern application codebases, custom exceptions are never serialized manually. So this pattern is most relevant when:
- a framework or library expects serializable exception types
- the exception crosses process or application boundaries
- tooling captures and reconstructs exception data
- you want a platform-conventional exception type for reusable libraries
If the exception stays entirely inside one process and carries no extra state, serialization support may never be exercised in practice. Even so, many teams still implement the standard pattern for completeness and compatibility.
Testing the Custom State
At a minimum, test that the custom properties survive construction and, if relevant to your environment, serialization flows. Even without a full serialization test, verifying the property values and constructor chaining catches most implementation mistakes.
The more data your exception carries, the more valuable these checks become.
Common Pitfalls
The most common pitfall is adding custom properties and forgetting to include them in GetObjectData and the serialization constructor.
Another pitfall is omitting one or more standard constructors. That makes the exception less compatible with common usage patterns, especially when wrapping inner exceptions.
Developers also forget to call base.GetObjectData(info, context). If you skip that call, base exception state may not be preserved correctly.
Finally, do not add a large amount of mutable business state to exceptions. Exceptions should explain failures, not become alternative transport objects.
Summary
- Mark the custom exception with
[Serializable]. - Provide the standard exception constructors, including the protected serialization constructor.
- Override
GetObjectDatawhen the exception adds custom properties. - Restore those custom properties from
SerializationInfoin the serialization constructor. - Keep exception payloads focused on error context rather than broad application state.

