Spargine is a collection of open-source assemblies and NuGet packages designed for .NET 10, which I have been developing and maintaining since the release of .NET Framework 2. These assemblies are not only a core part of my projects but are also actively deployed in production environments across several companies I collaborate with.
Get Spargine
You can access the source code and NuGet packages here:
- GitHub: Spargine 10
- NuGet: dotNetDaveNuGet
Trapping and inspecting exceptions is a fact of life in .NET development—but the platform itself gives you little more than the basics. While try/catch blocks and stack traces are useful, they fall short when you need deep insight into complex exception hierarchies, aggregate exceptions, or production-level logging and diagnostics.
That’s where the ExceptionExtensions class from the DotNetTips.Spargine.Extensions NuGet package shines. It gives you a powerful toolkit to analyze, traverse, format, serialize, and log exceptions with far greater precision and consistency than what .NET provides out of the box.
As engineers building production systems, our goal is not just to catch exceptions—it’s to understand them quickly, log them intelligently, and avoid turning logs into a chaotic mess. ExceptionExtensions was designed to solve exactly that problem.
Why ExceptionExtensions Matters
.NET provides only minimal built-in support for:
- Traversing nested exception hierarchies
- Flattening AggregateExceptions
- Collecting all messages and stack traces
- Preventing duplicate logging
- Serializing exceptions cleanly
- Distinguishing between recoverable, critical, and fatal errors
ExceptionExtensions fills these gaps and turns exception handling into a structured, reliable, and developer-friendly experience.
Available Methods
Exception Inspection & Traversal
- ContainsAggregateException()
Determines whether the exception or any of its inner exceptions is an AggregateException. - ContainsExceptionOfType()
Checks whether the exception or any of its inner exceptions is of a specified type. - ContainsMessage(string message)
Searches the exception hierarchy for a specific message. - GetAllInnerExceptions()
Retrieves all inner exceptions as a flat list. - TraverseFor()
Traverses the exception hierarchy to find a specific exception type. - FromHierarchy(Func<TSource, TSource> accumulatorFunction)
Returns a sequence representing the hierarchy starting from a source exception. Ideal for walking nested structures. - FromHierarchy(Func<TSource, TSource> nextItem, Func<TSource, bool> canContinuePredicate)
A more flexible hierarchy traversal method that lets you define when iteration should stop.
Message & Stack Trace Extraction
- GetAllMessages(char delimiter)
Concatenates all exception messages into a single string. - GetAllMessagesWithStackTrace()
Retrieves all messages and stack traces as a read-only collection, perfect for advanced logging. - FormatForDisplay()
Formats exception details into a clean, human-readable string suitable for UI or diagnostics.
Metadata & Serialization
- ExtractData()
Extracts all key-value pairs from Exception.Data. - GetMetadata()
Retrieves metadata associated with the exception. - ToJson()
Serializes the entire exception—including inner exceptions—into JSON. Ideal for telemetry, logging pipelines, or APIs.
Logging Support
- LogException(ILogger logger, LogLevel logLevel)
Logs the exception using the provided logger and Spargine’s FastLoggerExtensions, ensuring consistent and performant logging.
Severity Classification
- IsCritical()
Determines whether an exception is critical. Recognized critical types include:- NullReferenceException
- StackOverflowException
- OutOfMemoryException
- ThreadAbortException
- IndexOutOfRangeException
- AccessViolationException
- IsFatal()
Identifies exceptions severe enough to justify terminating the application (e.g., OutOfMemoryException). - IsSecurityOrCritical()
Returns true if the exception is either a SecurityException or one of the critical exception types.
Preventing Duplicate Logging
Logging the same exception more than once wastes time, bloats logs, and makes analysis harder. ExceptionExtensions solves this by letting you track whether an exception has already been logged.
Logged State Methods
- IsLogged()
Gets or sets whether the exception has been logged. - SetIsLogged()
Marks an exception as logged. - ClearLoggedState()
Clears the logged state so the exception can be logged again if needed.
This feature is invaluable in complex pipelines, background services, and global exception handlers where the same exception may flow through multiple layers.
Pro Tip
To standardize how exceptions are thrown across your codebase, pair ExceptionExtensions with the ExceptionThrower class from the DotNetTips.Spargine.Core assembly. It ensures consistent messages, consistent exception types, and cleaner code.
Summary
Exception handling shouldn’t stop at catching and rethrowing. With ExceptionExtensions, you gain:
- Deep insight into exception hierarchies
- Smarter, cleaner logging
- Protection against duplicate log entries
- Built-in severity classification
- JSON serialization for modern diagnostics
- Human-readable formatting for debugging and UI
The next time you’re building a global exception handler, debugging a production issue, or refining your logging strategy, let ExceptionExtensions do the heavy lifting. It transforms exception handling from a reactive chore into a powerful diagnostic advantage.
Get Involved!
The success of open-source projects like Spargine relies on community contributions. If you find these updates useful or have ideas for further improvements, I encourage you to contribute by:
- Submitting pull requests
- Reporting issues
- Suggesting new features
Your input is invaluable in making Spargine an even more powerful tool for the .NET community.
If you are interested in contributing or have any questions, feel free to contact me via email at dotnetdave@live.com. Your support and collaboration are greatly appreciated!
Thank you, and happy coding!
Pick up any books by David McCarter by going to Amazon.com: http://bit.ly/RockYourCodeBooks
Make a one-time donation
Make a monthly donation
Make a yearly donation
Choose an amount
Or enter a custom amount
Your contribution is appreciated.
Your contribution is appreciated.
Your contribution is appreciated.
DonateDonate monthlyDonate yearlyIf you liked this article, please buy David a cup of Coffee by going here: https://www.buymeacoffee.com/dotnetdave
© The information in this article is copywritten and cannot be preproduced in any way without express permission from David McCarter.
Discover more from dotNetTips.com
Subscribe to get the latest posts sent to your email.

