Errors Thrown In Future Threads Don't Report Complete Details In ColdFusion 2018
Earlier today, I took my first look at the Future data-type and the associated runAsync() method in ColdFusion 2018. In that post, I talked about the confusing behavior of the .then() and .error() methods which appear to be blocking calls on the parent thread. Another point of confusion and friction for me, as I've been experimenting with Futures, is the fact that errors thrown in a Future / asynchronous thread don't contain all of the information that we've historically depended upon as ColdFusion programmers. Specifically, these asynchronous errors exclude the "Detail", "ExtendedInfo", and "ErrorCode" fields; and, the fields that are included suppress or obfuscate some of the root-cause information.
Demonstrating this divergent error behavior is quite trivial. All we have to do is throw an error inside of runAsync() and then see what bubbles up to the surface. As a control, I'll use the same approach both inside and outside of a Future thread:
<cfscript>
public void function triggerError() {
throw(
type = "StreamsCrossed",
message = "It would be bad.",
detail = "Try to imagine all life as you know it stopping instantaneously.",
extendedInfo = "And, every molecule in your body exploding at the speed of light.",
errorCode = "Zuul"
);
}
public void function printError( required any error ) {
writeDump(
var = error,
label = "Control Error",
show = "type,message,detail,extendedInfo,errorCode"
);
}
// ------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------- //
// As a control-case, trigger the error in a normal try/catch.
try {
triggerError();
} catch ( any error ) {
printError( error );
}
// ------------------------------------------------------------------------------- //
// ------------------------------------------------------------------------------- //
future = runAsync( triggerError );
// Now, let's look at how that error gets reported in a Future.
try {
future.get();
} catch ( any error ) {
printError( error );
}
</cfscript>
As you can see, we're trigging the same error in both the parent context and the runAsync() thread context. And, we're using the same "print" method to output the error. And yet, when we run this code, we get the following output:
As you can see, the output of the two Error objects is wildly different. The former represents the standard we're used to dealing with in ColdFusion; and the latter, in my opinion, represents an incomplete Error object. Not only is the latter missing fields; but, the fields that it does include obfuscate or suppress the original error details.
This is an important behavior to consider because your ColdFusion application may contain error handling logic that assumes certain Error fields exist. This is a good reminder to be vigilant about testing dynamic data structures before they are consumed. That said, it would be nice to have access to the core Error. I have to assume the divergence is due to some limitation of the Future Thread boundary.
NOTE: That said, the ColdFusion documentation gives no indication that "Detail" is ever omitted, regardless of the Type of error.
Want to use code from this post? Check out the license.
Reader Comments
Ben - We will be fixing this, original exception will be exposed as the Cause of ExecutionException.
@Vijay,
Awesome! That's good to hear.
Great, it should go as a part of 2018 update.