Why does AWS Tools for Powershell ignore -ErrorAction SilentlyContinue?

81 views Asked by At

I want to get $null from the Get-IAMUser command in case the user does not exist.

I investigated using -ErrorAction SilentlyContinue but it seems to be ignored.

Line |
   3 |  if ($null -ne (Get-IAMUser -UserName SomeUserName))
     |                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     | The user with name SomeUserName cannot be found.

Is there a way to get rid of this error message?

2

There are 2 answers

1
Ermiya Eskandary On BEST ANSWER

Unfortunately, AWS Powershell modules heavily use terminating errors instead of non-terminating errors.

If they used non-terminating errors, we'd be able to use -ErrorAction SilentlyContinue to suppress the error message and continue with executing the script. However, passing -ErrorAction SilentlyContinue to AWS Powershell cmdlets usually has no effect and is 'ignored'.

The error is a terminating error so use try-catch instead.


Recommended approach:

$userName = 'random-string'

try {
    $iamUser = Get-IAMUser -UserName $userName
    Write-Host "User '$userName' exists."
} catch {
    Write-Host "User '$userName' does not exist."
}

Alternatively, if you want to really use if ($null -ne $iamUser):

$userName = 'random-string'

try {
    $iamUser = Get-IAMUser -UserName $userName
} catch {
    # will re-throw the exception if it does not relate to the "user not found" scenario
    if ($_.Exception.InnerException.ErrorCode -eq "NoSuchEntity") {
        $iamUser = $null
    } else {
        throw
    }
}

if ($null -ne $iamUser) {
    Write-Host "User '$userName' exists."
} else {
    Write-Host "User '$userName' does not exist."
}

Output:

User 'random-string' does not exist.

Note that most PowerShell Get-* commands don't throw terminating errors, and so there is currently an open feature request that hopefully is addressed in a future update...

2
mklement0 On

To complement Ermiya Eskandary's helpful answer:

An alternative approach is to take advantage of the - surprising - fact that $ErrorActionPreference preference variable does act on terminating errors too.
If you set it in a child scope and call the cmdlet from there - via & { ... } - the change is implicitly limited to that scope, so there's no need to restore the previous setting:

$iamUser = 
  & { $ErrorActionPreference = 'SilentlyContinue'; Get-IAMUser -UserName $userName }

Note:

  • If Get-IAMUser fails, $iamUser receives the "enumerable null", i.e. the special [System.Management.Automation.Internal.AutomationNull]::Value singleton that signifies "no pipeline output"; however in expression contexts this value behaves like $null, so that $null -eq $iamUser works correctly.

  • Even if the AWS cmdlets get fixed to emit non-terminating errors[1] - which can be silenced with the common -ErrorAction parameter - the awkward asymmetry between -ErrorAction and the seemingly equivalent $ErrorActionPreference preference variable (which acts on all errors) will remain.


[1] For guidance on when cmdlets should emit non-terminating vs. (statement-)terminating errors, see this answer. Note that non-terminating errors are much more common.