Skip to content

-ErrorAction Ignore doesn't work for calling advanced functions #1759

Closed

Description

  1. Create a script with the following code:
function foo
{
    [CmdletBinding()]
    param()

process
{
    try
    {
        Write-Error 'boo'
    }
    finally { }
}

}

function bar
{
    foo -ErrorAction Ignore
}
  1. Dot-source that script to import the function definitions.
  2. Call the "bar" function.

Expected result:
Nothing (no output; no error--bar is calling foo with "-ErrorAction Ignore").

Actual result:
I get an error, and it's not even the one written by foo:

Write-Error : The value Ignore is not supported for an ActionPreference variable. The provided value should be used only as a value for a preference
parameter, and has been replaced by the default value. For more information, see the Help topic, "about_Preference_Variables."
At E:\temp\ps_ea_ignore_2.ps1:11 char:13
-             Write-Error 'boo'
-             ~~~~~~~~~~~~~~~~~
  - CategoryInfo          : NotSpecified: (:) [Write-Error], NotSupportedException
  - FullyQualifiedErrorId : System.NotSupportedException,Microsoft.PowerShell.Commands.WriteErrorCommand

Dan Thompson:
In addition to being annoying for straight-up calling advanced functions (you can't use "-ErrorAction Ignore" with them), this also hampers meta-programming (you can't do "& $someCmd -ErrorAction Ignore", because you might not know if $someCmd is an advanced function or not).

Activity

  1. SteveL-MSFT commented on Sep 29, 2016

    @SteveL-MSFT
    MemberAuthor

    TFS:6868128

  2. added this to the milestone on Sep 29, 2016
  3. joeyaiello commented on May 24, 2017

    @joeyaiello
    Contributor

    This kinda stinks, but it's been there for a long time. I'm going to put it in the DevEx Project, and we can triage it against everything there.

  4. mklement0 commented on Dec 15, 2017

    @mklement0
    Contributor

    More specifically, I think what's going on is (disclaimer: haven't looked at the source code):

    When an advanced function is called, the -ErrorAction parameter value is translated into the $ErrorActionPreference variable value in the scope of the function, presumably so as to propagate the setting to calls to other cmdlets made inside the same function.

    The above is the cause of the problem: Ignore is not supported as a value of the preference variable, and the error message to that effect is triggered whenever something inside the advanced function writes to the error stream, including Write-Error itself.

    A simplified example:

    function Get-Foo {
        [CmdletBinding()] param ()
        # Output the function-scope $ErrorActionPreference variable's value.
        # NOTE: Only set if -ErrorAction ... was passed.
        (Get-Variable -Scope 0 ErrorActionPreference).Value
        # Trigger an error; if -ErrorAction Ignore was passed, this will
        # provoke the spurious "The value Ignore is not supported for an ActionPreference variable."
        # error.
        1 / 0
      }

    Sourcing this function and invoking it as Get-Foo -ErrorAction Ignore shows the problem.

  5. schittli commented on Sep 13, 2018

    @schittli

    …, but it's been there for a long time. …

    Just because something was there for a long time
    should never be an argument to decide a software development question.

    It's just a question of a short time until any maintained Software gets a new release and in PowerShell, a Script can define the least expected runtime version.

    So, it's no problem to let design errors disappear slowly and user-friendly :-)

  6. mklement0 commented on Nov 29, 2018

    @mklement0
    Contributor

    Yes, it would be nice to get that fixed soon.

    In the meantime, here is a workaround:

    Place the following statement at the start [of the begin block] of your advanced function:

    if ($ErrorActionPreference -eq 'Ignore') { 
      $ErrorActionPreference = 'Ignore' # create *local* variable with *string* value
    }

    This takes advantage of another bug, #3483:
    If you create a preference variable in a non-global scope, it isn't type-constrained, so the local $ErrorActionPreference instance truly contains the string 'Ignore'.

    Despite being a string, the value does take effect and, because the check that causes the unwanted error expects an instance of the proper enumeration type, [System.Management.Automation.ActionPreference], the check is effectively suppressed.

  7. 3 remaining items

  8. KirkMunro commented on Apr 18, 2019

    @KirkMunro
    Contributor

    I was just reading the code behind this, and I have to ask: given how common parameters work in PowerShell today, setting action preference variables to ensure that the desired behavior propagates to other commands, isn't this a PSScriptAnalyzer problem that is inappropriately being handled internally within PowerShell code?

    For reference, see this comment in ExecutionContext.cs.

    // We don't want to support "Ignore" as action preferences, as it leads to bad
    // scripting habits. They are only supported as cmdlet overrides.

    That feels very wrong to me, and it gets in the way of being able to do something really useful (using -ErrorAction Ignore as appropriate when invoking advanced functions).

    IMHO the best solution to this issue is to allow people to shoot themselves in the foot, but ensure that the tools they should be using (PSScriptAnalyzer directly or integrated into an editor like VS Code) properly flag that as red and identify that you should never set an action preference variable to Ignore, with proper guidance on how they should handle such things.

    That solution fixes this issue, and is positioned to do a much better job educating the scripter so that they know better in the future.

  9. scott1138 commented on Aug 18, 2019

    @scott1138

    Another use case - when running Pester tests it's useful to not have any output and let Pester handle the test case reporting.

  10. adamedx commented on Sep 25, 2019

    @adamedx

    Just adding to the chorus asking for a fix -- whatever the cause of the issue, the behavior makes no sense and hampers many scenarios. Please fix in PowerShell 6 and 7.

  11. KirkMunro commented on Sep 25, 2019

    @KirkMunro
    Contributor

    The fix for this was added to PowerShell 7 preview 4. This issue can be closed.

  12. adamedx commented on Sep 25, 2019

    @adamedx

    No 6 then? Whatever, I'll take it in 7 -- thanks!

  13. KirkMunro commented on Sep 25, 2019

    @KirkMunro
    Contributor

    Any changes to 6 at this point would only be made for security reasons.

  14. adamedx commented on Oct 22, 2019

    @adamedx

    yay

  15. daverickdunn commented on May 14, 2020

    @daverickdunn

    Still an issue in 7.1...

    Name             : ConsoleHost
    Version          : 7.1.0-preview.2
    InstanceId       : d67d4374-65bd-4b90-b638-f51a4d71cd03
    UI               : System.Management.Automation.Internal.Host.InternalHostUserInterface
    CurrentCulture   : en-GB
    CurrentUICulture : en-US
    PrivateData      : Microsoft.PowerShell.ConsoleHost+ConsoleColorProxy
    DebuggerEnabled  : True
    IsRunspacePushed : False
    Runspace         : System.Management.Automation.Runspaces.LocalRunspace
    
  16. vexx32 commented on May 14, 2020

    @vexx32
    Collaborator

    Richard Dunn (@daverickdunn) I'm not seeing it in 7.1preview2; can you share what you're doing that's making that show up for you?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Resolution-FixedThe issue is fixed.WG-Enginecore PowerShell engine, interpreter, and runtime

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions