I am responsible for an F# WPF application. It emails me when an unhandled exception occurs. Most of the time, I'm able to identify the source of the exception from the error message and stack trace. However, I occasionally get a message like the following, which does not include any of my code in the stack trace.
Summary:
Object reference not set to an instance of an object.
--------------
Details:
System.NullReferenceException:
Object reference not set to an instance of an object.
at Microsoft.FSharp.Control.CancellationTokenOps.Start@1234-1.Invoke(Exception e)
at <StartupCode$FSharp-Core>.$Control.loop@435-40(Trampoline this, FSharpFunc`2 action)
at Microsoft.FSharp.Control.Trampoline.ExecuteAction(FSharpFunc`2 firstAction)
at Microsoft.FSharp.Control.TrampolineHolder.Protect(FSharpFunc`2 firstAction)
at <StartupCode$FSharp-Core>[email protected](Object state)
at System.Threading.QueueUserWorkItemCallback.WaitCallback_Context(Object state)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()
at System.Threading.ThreadPoolWorkQueue.Dispatch()
at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()
What clues are available in this stack trace that might help me identify the source of this exception?
For example, I'm assuming the original exception is being thrown within an async
computation. (The majority of my async code is based on F# async blocks.) Could my NullReferenceException
have occurred anywhere in an async
block? I notice that the exception occurred within a Start()
method. Or is it? That Start()
method takes an Exception
instance so perhaps the exception was thrown before that. Does that tell me anything? I wonder if someone is familiar enough with the Microsoft.FSharp.Control.Trampoline
to point me in the right direction.
By the way, in my error handling code, I am careful about checking all the InnerExceptions
and handling AggregateExceptions
. So I think this is all the information available in the Exception instance, but I could be wrong.
I did a quick test. The following Console program generates the identical stack trace.
[<EntryPoint>]
let main argv =
async { printfn "Inside async block."
let o = null
o.GetType() |> ignore
} |> Async.Start
System.Console.ReadKey(true) |> ignore
0 // return an integer exit code
That tells me the following:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With