Run the following expressions:
"some invalid JSON string" | ConvertFrom-Json -ErrorAction Ignore
"some invalid JSON string" | ConvertFrom-Json -ErrorAction SilentlyContinue
Both expressions write no error to the console, and return either $null or the empty string.
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
> $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
If this is not the appropriate place to report bugs against v5.x, please let me know where I can.
@alastairs Could you please test this with recent Powershell 6 build?
@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! 馃憤
Some further information in case it's useful: my $ErrorActionPreference variable is set to "Stop".
@PowerShell/powershell-committee (subset of @HemantMahawar @lzybkr @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.
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+2still gets executed
If that's the case, then -ErrorAction should be respected, right?
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.
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):
ArgumentException is terminating at the PS level, the 2+2 should then not be executed. -ErrorAction. If ArgumentException was caught as a non-terminating error, -ErrorAction SilentlyContinue should silence the error. What am I missing here?
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
}
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.
Unless you have some more insight, @dantraMSFT, I'll probably open another issue and figure out what the intended behavior is supposed to be.
cc @BrucePay
Behavior with TerminatingError and Exception is inconsistent, not sure if intended.
Alright, I'm closing it, I'll follow up offline or in another issue.
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
@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.
Most helpful comment
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: