Description
Description
The logic implemented in ResourceManagerCmdletBase.HandleException() is roughly like this:
- if the exception is an AggregateException and contains a single inner exception, extract that inner exception;
1a) nb. current code will crash if the AggregateException contains more than one exception (!) - if the resulting exception is CloudException, wrap it in a ResourceManagerCloudException and throw;
- otherwise, throw the exception object without wrapping.
The problem is in step 3), because the code uses a simple throw sourceException;
statement, which treats the exception as a new exception, not a rethrow. As a consequence, the existing stack trace of sourceException is overwritten with a useless stack trace ending at ResourceManagerCmdletBase.HandleException()
. This makes troubleshooting issues such as #13038 unnecessarily difficult ("where did that InvalidOperationException come from...?").
Instead of throw
ing the exception as if it was a new one, HandleException()
could use ExceptionDispatchInfo
to rethrow the exception in a manner which preserves the original stack trace:
ExceptionDispatchInfo.Capture(sourceException).Throw();
Steps to reproduce, Environment data, Module versions, Debug output, Error output
See #13038. The exception is reported like this:
Exception - System.InvalidCastException: Specified cast is not valid.
at
Microsoft.Azure.Commands.ResourceManager.Cmdlets.Implementation.ResourceManagerCmdletBase.HandleException(ExceptionDisp
atchInfo capturedException)
at Microsoft.Azure.Commands.ResourceManager.Cmdlets.Implementation.ResourceManagerCmdletBase.ExecuteCmdlet()
at Microsoft.WindowsAzure.Commands.Utilities.Common.AzurePSCmdlet.ProcessRecord();
while the actual source of the error was at Microsoft.Azure.Commands.ResourceManager.Cmdlets.Implementation.CmdletBase.DeploymentCreateCmdlet.ShouldProcessGivenCurrentWhatIfFlagAndPreference()
. If the real stack trace was printed, it would have saved a considerable amount of time.