44

I have a powershell script using the Skytap API (REST). I would like to catch the error, if there is one, and try to display it.

For example, we are changing the IP:

Invoke-RestMethod -Uri https://cloud.skytap.com/configurations/XXXXXX/vms/YYYYYY/interfaces/ZZZZZZ?ip=10.0.0.1 -Method PUT -Headers $headers

If the IP is used somewhere else, I will get the 409 Conflict Error (Request is well-formed but conflicts with another resource or permission).

I would like to check if the error is 409 and then tell it to do something else about it.

afuzzyllama
  • 6,538
  • 5
  • 47
  • 64
user01230
  • 563
  • 1
  • 6
  • 16

4 Answers4

96

This is somewhat awkward but the only way to do it as far as I know without doing something more complicated like using .NET's WebRequest and ConvertFrom-Json (or whatever data format you are expecting).

try {
    Invoke-RestMethod ... your parameters here ... 
} catch {
    # Dig into the exception to get the Response details.
    # Note that value__ is not a typo.
    Write-Host "StatusCode:" $_.Exception.Response.StatusCode.value__ 
    Write-Host "StatusDescription:" $_.Exception.Response.StatusDescription
}
David Anderson
  • 8,306
  • 2
  • 27
  • 27
  • This didn't exactly work, but it helped me get on the right track. I ended up adding this line: `$exception = $_.Exception` and then accessed the parameters on that, since it seems to be some kind of Exception object. – Ehtesh Choudhury Oct 03 '18 at 00:57
  • 2
    You shouldn't have to assign `$_.Exception` to a different variable unless you are trying to access it outside the `catch` block or from code where `$_` has a different meaning (such as in the script blocks passed to `Where-Object`, `ForEach-Object` etc.). The `Exception` parameter in this case is of type `System.Net.WebException` so any documentation about that type will be relevant. Also worth noting that my sample code is a bit oversimplified. In production code, you'd want to account for the possibility of different `Exception` types but I felt that was out of scope for this question. – David Anderson Oct 03 '18 at 15:29
  • This did not work for me either, I think because the problem I was testing for is no response ;). `$_.Exception.Message` works great. –  Oct 01 '19 at 17:44
  • @ScottBeeson `$_.Exception.Message` will give you something different than what this question was asking for, but, yeah, that would be a good place to look for a hopefully useful error message when you either don't need the parsed out response code or don't have a response (which you can add a check for in my code above before trying to access its properties). – David Anderson Oct 01 '19 at 18:55
9

I know you asked for Powershellv4, but since v6/v7 :

Try {
     $WebRequestResult = Invoke-RestMethod -Uri $URL -Headers $Headers -Body $BodyJSON -Method $Method -ContentType $ContentType -SkipCertificateCheck
} Catch {
    if($_.ErrorDetails.Message) {
        Write-Host $_.ErrorDetails.Message
    } else {
        Write-Host $_
    }
}
MeGoodGuy
  • 395
  • 2
  • 10
6

Powershell 7 introduces the -SkipHttpErrorCheck parameter. This instructs the cmdlet to behave in a similar way to web requests in programming frameworks (i.e. where 404, 409, etc. are valid responses - the web request is successful but the server returned an error code).

This can be combined with the -StatusCodeVariable parameter. This instructs the cmdlet to insert the response code into a variable. However, the variable name is passed as a string (not as a reference). For example:

$scv = $null
Invoke-RestMethod ... -SkipHttpErrorCheck -StatusCodeVariable "scv"
John
  • 1,043
  • 15
  • 20
1

The Special Variable $? will solve this. It stands for $LASTEXITCODE = 0 (everything ok). It will ask for the Result Code from the previous Command.

Invoke-RestMethod -Uri https://cloud.skytap.com/configurations/XXXXXX/vms/YYYYYY/interfaces/ZZZZZZ?ip=10.0.0.1 -Method PUT -Headers $headers
    
if (!$?) {
    throw $_.ErrorDetails.Message
}
Gill-Bates
  • 559
  • 8
  • 22
  • It works, the additional doc is here https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_automatic_variables?view=powershell-7.1#section-1 – Muflix Sep 21 '21 at 12:55
  • The code as provided above will fail to throw a valid error message. $_ is not set when an error has occurred. Automatic variable $Error is however. – killercowuk May 17 '23 at 11:46