Find the inner-most exception without using a while loop?
Solution 1
Oneliner :)
while (e.InnerException != null) e = e.InnerException;
Obviously, you can't make it any simpler.
As said in this answer by Glenn McElhoe, it's the only reliable way.
Solution 2
I believe Exception.GetBaseException()
does the same thing as these solutions.
Caveat: From various comments we've figured out it doesn't always literally do the same thing, and in some cases the recursive/iterating solution will get you further. It is usually the innermost exception, which is disappointingly inconsistent, thanks to certain types of Exceptions that override the default. However if you catch specific types of exceptions and make reasonably sure they're not oddballs (like AggregateException) then I would expect it gets the legitimate innermost/earliest exception.
Solution 3
Looping through InnerExceptions is the only reliable way.
If the caught exception is an AggregateException, then GetBaseException()
returns only the innermost AggregateException.
http://msdn.microsoft.com/en-us/library/system.aggregateexception.getbaseexception.aspx
Solution 4
If you don't know how deep the inner exceptions are nested, there is no way around a loop or recursion.
Of course, you can define an extension method that abstracts this away:
public static class ExceptionExtensions
{
public static Exception GetInnermostException(this Exception e)
{
if (e == null)
{
throw new ArgumentNullException("e");
}
while (e.InnerException != null)
{
e = e.InnerException;
}
return e;
}
}
Solution 5
I know this is an old post, but I'm surprised nobody suggested GetBaseException()
which is a method on the Exception
class:
catch (Exception x)
{
var baseException = x.GetBaseException();
}
This has been around since .NET 1.1. Documentation here: http://msdn.microsoft.com/en-us/library/system.exception.getbaseexception(v=vs.71).aspx
Daniel T.
Updated on March 07, 2020Comments
-
Daniel T. about 4 years
When C# throws an exception, it can have an inner exception. What I want to do is get the inner-most exception, or in other words, the leaf exception that doesn't have an inner exception. I can do this in a while loop:
while (e.InnerException != null) { e = e.InnerException; }
But I was wondering if there was some one-liner I could use to do this instead.
-
Jay over 12 years+1 There is nothing like knowing the BCL to avoid convoluted solutions. Clearly, this is the most correct answer.
-
codingoutloud almost 11 yearsGetBaseException() method does this w/o a loop. msdn.microsoft.com/en-us/library/…
-
Tarik almost 11 yearsFor some reason,
GetBaseException()
didn't return the very first root exception. -
Tarik almost 11 yearsThis works whereas
Exception.GetBaseException()
didn't for me. -
Josh Sutterfield over 10 yearsGlenn McElhoe pointed out that indeed GetBaseException() does not always do what MSDN suggests we can expect in general (that "the Exception that is the root cause of one or more subsequent exceptions"). In AggregateException it is limited to the lowest exception of the same type, and perhaps there are others.
-
Josh Sutterfield over 10 yearsGood catch. Thanks - that explains the comments above where that answer was not working for some people. This makes it clear that MSDN's general description of "root cause of one or more subsequent exceptions" is not always what you'd assume since derived classes may override it. The real rule seems to be that all exceptions in a chain of exceptions "agree" on GetBaseException() & return the same object, which seems to be the case for AggregateException.
-
Giovanni B about 9 yearsDoesn't work for my issue. I have a few more levels down than what this is providing.
-
Michael R almost 9 yearsI used this
ex.GetBaseException().GetBaseException().GetBaseException()
to get to the deeptest exception. -
Chris Ballance over 8 years
GetBaseException()
did not work for me, because the top-most exception is an AggregateException. -
Kiquenet over 8 yearsUseful
public static Exception GetOriginalException(this Exception ex) { if (ex.InnerException == null) return ex; return ex.InnerException.GetOriginalException(); }
-
Federico Navarrete about 6 yearsThanks for your solution! Few people think in VB :D
-
Yoda about 6 yearsAnd there's a reason why! :P
-
Kiquenet about 6 yearsWhat's about
Exception.GetBaseException()
? -
Kiquenet about 6 yearsNot applies
AggregateException.InnerExceptions
? -
armadillo.mx almost 6 yearsIndeed was indicated before on December 5, 2012
-
Mohammad Reza Sadreddini over 2 yearsWouldent this code change the "e" source exception? and Shouldnt we make a copy of "e" before assigning InnerException to it? I suggest: var copyOfException = e; while (copyOfException.InnerException != null) copyOfException = copyOfException.InnerException;
-
Josh Sutterfield over 2 yearsHonestly with AggregateException there is no base exception per se, because there are multiple exceptions, each having a base exception. You would almost need a new AggregateException strictly reflecting the base exceptions of each exception in the original AggregateException. But that's not a real thrown exception. For AggregateException the ideal call would be plural, i.e.
Exception[] GetBaseExceptions()
but that's not a thing.