Skip to content

ResourceManagerCmdletBase exception handling logic destroys original exception stack trace #13050

Open
@jberezanski-mdg

Description

@jberezanski-mdg

Description

The logic implemented in ResourceManagerCmdletBase.HandleException() is roughly like this:

  1. 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 (!)
  2. if the resulting exception is CloudException, wrap it in a ResourceManagerCloudException and throw;
  3. 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 throwing 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.

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions