Rye bread
Rye bread

Reputation: 1811

Exception.ToString() throws exception

I am trying to log an exception using the Exception.ToString() method. However, I get a new exception from the ToString() method - it seems to originate from the stack trace handling. The original error is a FileNotFoundException. Here is the output:

The process was terminated due to an unhandled exception.
Exception Info: System.IO.FileNotFoundException
   at System.Signature.GetSignature(Void*, Int32, System.RuntimeFieldHandleInternal, System.IRuntimeMethodInfo, System.RuntimeType)
   at System.Reflection.RuntimeMethodInfo.FetchNonReturnParameters()
   at System.Reflection.RuntimeMethodInfo.GetParameters()
   at System.Diagnostics.StackTrace.ToString(TraceFormat)
   at System.Environment.GetStackTrace(System.Exception, Boolean)
   at System.Exception.GetStackTrace(Boolean)
   at System.Exception.get_StackTrace()
   at System.IO.FileNotFoundException.ToString()
   at InSQLMDASDriver.InSQLMDASDriver.Init(System.String, System.String)
   at InSQLMDASDriver.InSQLMDASDriverLogic.InSQLMDASDriverLogicInit(System.String, System.String)
   at InSQLMDASDriver.InSQLMDASDriverLogic..ctor(System.String, System.String)
   at InSQLMDASDriverWCFServer.Service1.MainTread()
   at System.Threading.ThreadHelper.ThreadStart_Context(System.Object)
   at System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
   at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
   at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object)
   at System.Threading.ThreadHelper.ThreadStart()

When I run this code I can verify that the exception is thrown from Exception.ToString():

    private void Init(string defaultWindowName, string mainPath)
    {    
       try 
       {

            // code that fails

        }
        catch(FileNotFoundException e)
        {
             string errorAsString = GetErrorAsString(e);

             Logger.Log(string.Format("Init error at line block {0}: {1}", initBlockCounter, errorAsString), level: LogLevel.Error);


             throw new Exception("FileNotFoundException: " + e.FileName + ", " + e.FusionLog, e);
       }
       catch (Exception e)
       {
              string errorAsString = GetErrorAsString(e);

              Logger.Log(string.Format("Init error at line block {0}: {1}", initBlockCounter, errorAsString), level: LogLevel.Error);


          throw;
      }
}

    string GetErrorAsString(Exception e)
    {
         try
         {
             return e.ToString();
         }
         catch(Exception ne)
         {
                     return e.Message + " (ERROR getting stacktrace: " + ne.Message + ")";
          }
    }

Why does this happen..?

Upvotes: 2

Views: 2976

Answers (1)

Rye bread
Rye bread

Reputation: 1811

Here is a description that matches my issue where an assembly failing to load causes a FileNotFoundException, and calling ToString() gives another exception:

Here is what happens. The Newtonsoft.Json.JsonConvert.DeserializeObject needs System.Runtime.Serialization.Primitives assembly. But it is not present, so it tries to throw the FileNotFoundException. It creates the exception object and then it wants to set the stack trace for it. So it looks at the topmost frame of the exception stack trace, finds the Newtonsoft.Json.JsonConvert.DeserializeObject method there and tries to use reflection to get its parameters info. When looking at the 2nd parameter of the method which is of type Newtonsoft.Json.JsonSerializerSettings, it tries to build the metadata structure for this parameter type. And accidentally, one of the fields of this type is of the StreamingContext type that comes from the System.Runtime.Serialization.Primitives assembly. To get details on the type, it attempts to load this assembly - and since it doesn't exist (that was the reason for the original exception we are trying to build stack trace for), it throws an exception and the result is what you can see.

See the bug report and discussion there: https://github.com/dotnet/runtime/issues/5203. It should be fixed meanwhile.

Upvotes: 4

Related Questions