Skip to content

Preventing setting 'Ignore' as the $ErrorActionPreference value is poorly enforced on the command line, and not at all in scripts #4348

Closed

Description

Related: #1759

The Ignore error-action value is meant to be used only with the -ErrorAction common parameter, not with the $ErrorActionPreference preference variable.

An explicit check to prevent the latter was clearly implemented (as evidenced by error message 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.), but it doesn't / doesn't properly take effect.

Steps to reproduce

  • On the command line:
# On the command line: set to invalid value, reflect it, then trigger an error, then reflect it again.
> $ErrorActionPreference = 'Ignore'; $ErrorActionPreference; 1 / 0; $ErrorActionPreference
  • In a script (place code in a *.ps1 file):
$ErrorActionPreference = 'Ignore'; $ErrorActionPreference; 1/0; $ErrorActionPreference

Expected behavior

  • Both on the command line and in a script:
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.
...
Continue
Attempted to divide by zero.
...
Continue

Actual behavior

  • On the command line:
Ignore
$ErrorActionPreference = 'Ignore'; $ErrorActionPreference; 1 / 0: 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."
    + CategoryInfo          : NotSpecified: (:) [], NotSupportedException
    + FullyQualifiedErrorId : System.NotSupportedException
Continue

The value was accepted at first and retained until the next error occurred. The next error's message is mistakenly replaced with the invalid-$ErrorActionPreference-value error message, and the value is reset to Continue at that point.

  • In a script:
Ignore
Ignore

The value was accepted, stayed in effect, and suppressed the statement-terminating error.

Environment data

PowerShell Core v6.0.0-beta.4 on macOS 10.12.5
PowerShell Core v6.0.0-beta.4 on Ubuntu 16.04.2 LTS
PowerShell Core v6.0.0-beta.4 on Microsoft Windows 10 Pro (64-bit; v10.0.15063)
Windows PowerShell v5.1.15063.413 on Microsoft Windows 10 Pro (64-bit; v10.0.15063)

Activity

  1. added
    WG-Enginecore PowerShell engine, interpreter, and runtime
    Issue-BugIssue has been identified as a bug in the product
    on Jul 27, 2017
  2. KirkMunro commented on Apr 16, 2019

    @KirkMunro
    Contributor

    Related to this, this issue drives me crazy:

    function Test-EAPreference {
        [CmdletBinding()]
        param()
        1/0
    }
    
    Test-EAPreference -ErrorAction Ignore

    The results of this command are as follows:

    Test-EAPreference : 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 line:1 char:1
    + Test-EAPreference -ErrorAction Ignore
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [Test-EAPreference], NotSupportedException
    + FullyQualifiedErrorId : System.NotSupportedException,Test-EAPreference
    

    According to docs, that's a bug, correct? Because technically the function is setting ErrorActionPreference, but from an end user's perspective, they're just using Ignore with -ErrorAction which should work just fine. I felt it was worth mentioning with this bug because this is a scenario where the prevention logic is being too strict, causing a bug.

  3. mklement0 commented on Apr 16, 2019

    @mklement0
    ContributorAuthor

    Indeed, Kirk Munro (@KirkMunro). What you're describing is the subject of #1759, which also shows workarounds.

  4. KirkMunro commented on Apr 18, 2019

    @KirkMunro
    Contributor

    Just to highlight it here as well for visibility, the best solution to this issue seems to be:

    1. Remove all logic that tries to prevent any action preference variable from being used as is when it has a value of Ignore.
    2. Add a new PSScriptAnalyzer rule that flags the direct assignment of any action preference variable to Ignore (via the equals operator or Set-Variable) as red, with appropriate documentation for that rule explaining why that's dangerous and what should be done instead.

    Also shared over here.

  5. KirkMunro commented on Apr 27, 2019

    @KirkMunro
    Contributor

    There's more to this. The fact that it works in a script is simply because the logic internally was written incorrectly, only preventing $ErrorActionPreference from having a value of [System.Management.Automation.ActionPreference]::Ignore (e.g. an enumerated value). Having a value that is of type string (which is what happens whenever you create a locally scoped $ErrorActionPreference value -- it doesn't have to be in a script at all) allows Ignore to work just fine. You can also delete the top level $ErrorActionPreference variable, which is strongly typed as an ActionPreference, and then recreate it as a string and again it works.

    For example:

    Remove-Variable -Name ErrorActionPreference
    [string]$ErrorActionPreference = 'Ignore'
    function Test-Ignore {
        [CmdletBinding()]
        param()
        Get-Process -Id 12345678
    }
    Test-Ignore # Ignores the error because it uses the ErrorActionPreference variable of type string
    Test-Ignore -ErrorAction Ignore # Raises the error about using Ignore because internally it creates a strongly typed ErrorActionPreference variable of type ActionPreference, sets the value as Ignore, and then when an error comes up that would otherwise be ignored, generates the `NotSupportedException`.

    That, combined with the example below, demonstrates how terrible a job PowerShell is doing in this case, when really this is a linting problem, not something that the parser/compiler/interpreter should care about at all.

    function Test-Ignore2 {
        [CmdletBinding()]
        param()
        'No errors to see here, move along'
    }
    Test-Ignore2 -ErrorAction Ignore # I can use this for functions some of the time, as long as they don't have errors to ignore? *sigh*

    Steve Lee (@SteveL-MSFT): Here's one for a committee meeting. Please give the green light to just remove the nonsensical code blocking Ignore from $ErrorActionPreference (but only some of the time, as this illustrates), in favor of a PSSA rule to warn folks who don't know better instead.

  6. KirkMunro commented on Apr 27, 2019

    @KirkMunro
    Contributor

    To add an additional thought for the committee: ActionPreference.Suspend is not supported in PowerShell Core (it's only used for workflows), and today it just adds confusion to the code with checks to ensure that value isn't used where there doesn't need to be any (plus some of those checks suffer the same issues identified for ActionPreference.Ignore, since they use the same logic). Do we need to keep ActionPreference.Suspend around at this point or can we just chuck it and the half-dozen checks related to it?

  7. joeyaiello commented on May 8, 2019

    @joeyaiello
    Contributor

    Sorry for the ignorance here (and mostly this is a note to myself for a Committee discussion later today), but why is setting EAP to Ignore dangerous?

  8. vexx32 commented on May 8, 2019

    @vexx32
    Collaborator

    Mainly because it effectively disables all possibility to handle non-terminating errors if you're not aware it's been set. For example, say you don't quite understand the gravity of it, and you set it in your profile.

    Many commands will now simply cease to provide output, with no apparent reason as to why. No errors are generated or stored in $error, nothing is displayed. It's possible that for some poorly-designed commands or functions that this could be actually harmful, but in my mind it would mostly hurt the user experience for those less familiar with the language.

    That said, it probably isn't that huge of a concern, really.

  9. added
    Committee-ReviewedPS-Committee has reviewed this and made a decision
    and removed
    Review - CommitteeThe PR/Issue needs a review from the PowerShell Committee
    on May 8, 2019
  10. SteveL-MSFT commented on May 8, 2019

    @SteveL-MSFT
    Member

    @PowerShell/powershell-committee reviewed this and agrees that the check for Ignore should be removed and allow the user to set what they want. Separately, we should have a PSScriptAnalyzer rule to detect and recommend against setting EAP.

  11. KirkMunro commented on May 9, 2019

    @KirkMunro
    Contributor
  12. SteveL-MSFT commented on May 9, 2019

    @SteveL-MSFT
    Member

    Kirk Munro (@KirkMunro) sorry we missed that. Can you open a new issue on that and cc me to mark for @PowerShell/powershell-committee review? Thanks.

  13. KirkMunro commented on May 9, 2019

    @KirkMunro
    Contributor

    FYI, I already included a fix for this as part of PR #8205.

  14. KirkMunro commented on Sep 25, 2019

    @KirkMunro
    Contributor

    The fix for this was to allow ActionPreference.Ignore to be assigned to any action preference variable, which allows it to be used in functions as well. This fix was merged and included in PowerShell 7 preview 4. I believe this issue can be closed.

  15. vexx32 commented on Sep 25, 2019

    @vexx32
    Collaborator
  16. daxian-dbw commented on Sep 25, 2019

    @daxian-dbw
    Member

    Fixed by #10317

  17. iSazonov commented on Sep 26, 2019

    @iSazonov
    Collaborator

    Kirk Munro (@KirkMunro) Thanks for fixing this!

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

    Committee-ReviewedPS-Committee has reviewed this and made a decisionIssue-BugIssue has been identified as a bug in the productResolution-FixedThe issue is fixed.WG-Enginecore PowerShell engine, interpreter, and runtime

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions