Skip to content

ConvertFrom-Json does not respect -ErrorAction #2860

Closed

Description

Steps to reproduce

Run the following expressions:

"some invalid JSON string" | ConvertFrom-Json -ErrorAction Ignore
"some invalid JSON string" | ConvertFrom-Json -ErrorAction SilentlyContinue

Expected behavior

Both expressions write no error to the console, and return either $null or the empty string.

Actual behavior

The expressions write an error to the console and throw the following exception:

ConvertFrom-Json : Invalid JSON primitive: some invalid JSON string.
At line:1 char:12
+ "some invalid JSON string" | ConvertFrom-Json -ErrorAction Ignore
+            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [ConvertFrom-Json], ArgumentException
    + FullyQualifiedErrorId : System.ArgumentException,Microsoft.PowerShell.Commands.ConvertFromJsonCommand

Environment data

> $PSVersionTable

Name                           Value
----                           -----
PSVersion                      5.1.14393.206
PSEdition                      Desktop
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
BuildVersion                   10.0.14393.206
CLRVersion                     4.0.30319.42000
WSManStackVersion              3.0
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1

Activity

  1. alastairs commented on Dec 8, 2016

    @alastairs
    Author

    If this is not the appropriate place to report bugs against v5.x, please let me know where I can.

  2. iSazonov commented on Dec 8, 2016

    @iSazonov
    Collaborator

    Alastair Smith (@alastairs) Could you please test this with recent Powershell 6 build?

  3. alastairs commented on Dec 8, 2016

    @alastairs
    Author

    Ilya (@iSazonov) The behaviour is the same with 6.0.0-alpha13

    > $PSVersionTable
    
    Name                           Value
    ----                           -----
    PSEdition                      Core
    PSVersion                      6.0.0-alpha
    PSRemotingProtocolVersion      2.3
    PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
    WSManStackVersion              3.0
    CLRVersion
    GitCommitId                    v6.0.0-alpha.13
    BuildVersion                   3.0.0.0
    SerializationVersion           1.1.0.1

    BTW, I love that trying this out was just a case of extracting a zip file somewhere and not a full-blow installer. Great work! 👍

  4. alastairs commented on Dec 8, 2016

    @alastairs
    Author

    Some further information in case it's useful: my $ErrorActionPreference variable is set to "Stop".

  5. added this to the milestone on Jan 23, 2017
  6. joeyaiello commented on Feb 16, 2017

    @joeyaiello
    Contributor

    @PowerShell/powershell-committee (subset of Hemant Mahawar (@HemantMahawar) Jason Shirk (@lzybkr) Kenneth Hansen (@khansen00) and myself) agree that the original issue (#2860) is by design. It is unreasonable for ConvertFrom-Json to emit anything but an error when receiving malformed input, and terminating errors are not respected by -ErrorAction. If a developer absolutely wants to make a conscious choice to ignore that terminating error, they should use try/catch.

  7. removed this from the milestone on Feb 16, 2017
  8. added this to the milestone on Feb 28, 2017
  9. joeyaiello commented on Apr 13, 2017

    @joeyaiello
    Contributor

    Okay, now I actually don't know what's going on. It would appear that this is currently a non-terminating error:

    ConvertFrom-Json : Conversion from JSON failed with error: Unexpected character encountered while parsing value: s.
    Path '', line 0, position 0.
    At line:1 char:18
    + "some invalid" | ConvertFrom-Json -ErrorAction SilentlyContinue; 2+2
    +                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        + CategoryInfo          : NotSpecified: (:) [ConvertFrom-Json], ArgumentException
        + FullyQualifiedErrorId : System.ArgumentException,Microsoft.PowerShell.Commands.ConvertFromJsonCommand
    
    4
    

    Note: the 2+2 still gets executed

    If that's the case, then -ErrorAction should be respected, right?

  10. dantraMSFT commented on Apr 13, 2017

    @dantraMSFT
    Contributor

    Joey,
    The proposed fix for this was not accepted and resolved as by-design. Under the hood, Json.Net throws an ArgumentException for malformed json content.

  11. joeyaiello commented on Apr 14, 2017

    @joeyaiello
    Contributor

    Then I'm not understanding why it's not terminating the statement above....my understanding of PS errors (which may be busted, but please help me understand):

    • terminating errors (usually surfaced from internal exceptions) should terminate the script block or statement. In this case, if the ArgumentException is terminating at the PS level, the 2+2 should then not be executed.
    • Non-terminating errors respect -ErrorAction. If ArgumentException was caught as a non-terminating error, -ErrorAction SilentlyContinue should silence the error.

    What am I missing here?

  12. dantraMSFT commented on Apr 14, 2017

    @dantraMSFT
    Contributor

    This appears to be a side-effect of Cmdlet.ThrowTerminatingError; -ErrorAction is apparently ignored. It's not clear if it is intentional. I see the same behavior on Windows PowerShell.
    Here's a couple of PS functions that illustrate the behavior difference:

    function TerminatingError
    {
        $exception = [System.ArgumentException]::new("argexception")
        $err = [System.Management.Automation.ErrorRecord]::new( `
            $exception,`
            'error',`
            [System.Management.Automation.ErrorCategory]::NotSpecified,`
            $null)
        $cmdlet = [Microsoft.PowerShell.Commands.GetDateCommand]::new()
        $cmdlet.ThrowTerminatingError($err)
    }
    
    function ExceptionError
    {
        $exception = [System.ArgumentException]::new("argexception")
        throw $exception
    }
  13. joeyaiello commented on Apr 14, 2017

    @joeyaiello
    Contributor

    Okay, now I really don't know what's going on. With your two functions, TerminatingError;2+2 shows that it's not really terminating, but ExceptionError;2+2 is terminating.

  14. joeyaiello commented on Apr 14, 2017

    @joeyaiello
    Contributor

    Unless you have some more insight, Dan Travison (@dantraMSFT), I'll probably open another issue and figure out what the intended behavior is supposed to be.

  15. SteveL-MSFT commented on Apr 14, 2017

    @SteveL-MSFT
    Member

    cc Bruce Payette (@BrucePay)

    Behavior with TerminatingError and Exception is inconsistent, not sure if intended.

  16. joeyaiello commented on Apr 17, 2017

    @joeyaiello
    Contributor

    Alright, I'm closing it, I'll follow up offline or in another issue.

  17. joeyaiello commented on Apr 18, 2017

    @joeyaiello
    Contributor

    For posterity, my understanding of terminating errors was wrong. A terminating error cancels execution of the current pipeline or expression, not of an entire script block.

    A better way to check for terminating errors is to just use try/catch:

    C:\Program Files\PowerShell\6.0.0-alpha.18> try {"fdasf" | convertfrom-json} catch {1}
    1
    C:\Program Files\PowerShell\6.0.0-alpha.18> try {ls foo} catch {1}
    ls : Cannot find path 'C:\Program Files\PowerShell\6.0.0-alpha.18\foo' because it does not exist.
    At line:1 char:6
    + try {ls foo} catch {1}
    +      ~~~~~~
        + CategoryInfo          : ObjectNotFound: (C:\Program File....0-alpha.18\foo:String) [Get-ChildItem], ItemNotFound
       Exception
        + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetChildItemCommand
  18. mklement0 commented on Aug 15, 2017

    @mklement0
    Contributor

    Joey Aiello (@joeyaiello):

    I had the same misconception, and I think the source is that the current help topics conflate statement-terminating errors with script-terminating errors - please see Our Error Handling, Ourselves - time to fully understand and properly document PowerShell's error handling.

  19. awsles commented on May 23, 2021

    @awsles

    I know this is an old closed issue... but using "resolvedByDesign" as an excuse is lame... The optics of this is taht an error is an error is an error, irrespective of terminating or non-terminating. Thus-ErrorAction should be respected for all errors and cmdlets, or it becomes inconsistent and unpredictable. End developers should be free to use errorAction as they see fit.

    $json = ("apple" | convertFrom-json -ErrorAction SilentlyContinue)
    if (!$json) { write-warning "Issue with json input - ignoring" }
    

    OR maybe we need -TerminatingErrorAction as a new switch? 😊

  20. gerardog commented on Oct 10, 2024

    @gerardog

    I find ConvertFrom-Json not respecting -ErrorAction counterintuitive and a poor user experience.

    I'm reading a stream of one-line json's, and try catch can't be embedded in a pipeline, so here is my workaround:
    kubectl logs my-pod | ConvertFrom-JsonSafe

    function ConvertFrom-JsonSafe {
        [CmdletBinding()]
        param (
            [Parameter(ValueFromPipeline, Mandatory=$true)]
            [string]$InputObject,
            [Switch]$Quiet
        )
    
        process {
            try {
                $InputObject | ConvertFrom-Json
            } catch {
                # If $Quiet is not set, log a warning
                if (-not $Quiet) {
                    Write-Warning "Failed to convert JSON: $InputObject"
                }
            }
        }
    }
    
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

Committee-ReviewedPS-Committee has reviewed this and made a decisionResolution-By DesignThe reported behavior is by design.WG-Cmdletsgeneral cmdlet issues

Type

No type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions