Track tasks and feature requests
Join 40 million developers who use GitHub issues to help identify, assign, and keep track of the features and bug fixes your projects need.
Sign up for free See pricing for teams and enterprisesSuggestion: Add an $ErrorView option that displays concise, single-line error information and consider making that the default - default formatting of ErrorRecord #3647
Comments
This comment has been minimized.
This comment has been minimized.
|
I agree - there is a ton of room for improvement. I do think the default view needs to be smart - e.g. the position information is sometimes useless, sometimes not. Maybe some heuristics are needed to decide when to show the error position. For example, if it's a PowerShell parser error, it's probably useful. If it's the entire line, maybe not. But maybe showing the line is useful. It's easy enough to override the default error view with your own custom |
lzybkr
added
Issue-Enhancement
Up-for-Grabs
labels
Apr 26, 2017
This comment has been minimized.
This comment has been minimized.
|
This becomes somewhat tricky because not all exception messages contain the target against which the action is taking place. |
This comment has been minimized.
This comment has been minimized.
dragonwolf83
commented
Apr 27, 2017
|
Wouldn't changing I think what most of us are wanting is a view that just gives the Exception Message or maybe the same information but formatted better. This could be the Option 1: CommandName: Get-Item
Exception Message: Cannot find path '/NoSuch' because it does not exist.Option 2: Get-Item: Cannot find path '/NoSuch' because it does not exist.Option 3: Get-Item: Cannot find path '/NoSuch' because it does not exist. At line:1 char:1Either one of those gives a simple view of the error that can be acted upon. |
This comment has been minimized.
This comment has been minimized.
|
@dragonwolf83: I don't think there's a need to change Yes, it's a challenge to come up with a concise message that still contains all relevant information for a human to get the gist of the problem at a glance. It seems to me that To elaborate on the motivation:
I agree with @lzybkr that heuristics and smarts are needed, because different properties are relevant to different errors; I'll see if I can come up with a prototype. |
This comment has been minimized.
This comment has been minimized.
|
@mklement0 |
This comment has been minimized.
This comment has been minimized.
|
At the bottom is a script you can run as-is, which redefines the default error view and outputs a few sample errors. Here are the sample error representations, preceded by the commands that triggered them, as run on a Ubuntu system: # Expression-statement-terminating error (from an all-PS expression)
1 / 0
>>>1 / 0<<<: Attempted to divide by zero. (At /tmp/2294.ps1:5 char:7)
------------------------
# Expression-statement-terminating error (from a .NET method call)
[int]::Parse('not-a-number')
>>>[int]::Parse('not-a-number')<<<: Exception calling "Parse" with "1" argument(s): "Input string was not in a correct format." (At /tmp/2294.ps1:12 char:7)
------------------------
# Non-terminating error
Get-Item /NoSuchItem
Get-Item: Cannot find path '/NoSuchItem' because it does not exist. (At /tmp/2294.ps1:19 char:7)
------------------------
# Pipeline-statement-terminating error
Get-Item -NoSuchParam
Get-Item: A parameter cannot be found that matches parameter name 'NoSuchParam'. (At /tmp/2294.ps1:26 char:16)
------------------------
# Indirect parse error, via Invoke-Expression. (If we tried ``1 * 2)`` directly in a script, the whole script would fail to parse.)
Invoke-Expression '1 * 2)'
PARSE ERROR: Invoke-Expression: 1 * 2)<<< Unexpected token ')' in expression or statement. (At /tmp/2294.ps1:33 char:7)
------------------------
# Remoting (job) error
Receive-Job -Wait -AutoRemoveJob (Start-Job { Get-Item /NoSuchItem })
[localhost] Get-Item: Cannot find path '/NoSuchItem' because it does not exist. (remoting/job)
------------------------
# Script-terminating error, via Throw
Remove-Item $PSCommandPath # Since the Throw statement terminates the script
Throw "Not at $HOME"
STOPPED: >>>Throw "Not at $HOME"<<<: Not at /home/jdoe (At /tmp/2294.ps1:49 char:7)The overall format is: [[<computer-name>] ]<immediate-error-source>: <message>[ (<context/position>)]Things to note:
|
This comment has been minimized.
This comment has been minimized.
|
To help with experimenting, find helper function E.g.: gi /NoSuch; out-ErrorDetailsyields the following:
Function
|
mklement0
changed the title
Suggestion: Add an $ErrorView option that displays concise, single-line error information and consider making that the default
Suggestion: Add an $ErrorView option that displays concise, single-line error information and consider making that the default - default formatting of ErrorRecord
Aug 26, 2017
This comment has been minimized.
This comment has been minimized.
|
I would also suggest that non-terminating errors have a different color (magenta?) than terminating errors |
This comment has been minimized.
This comment has been minimized.
|
That's a great idea, but - given just a If we clear that hurdle, we also need to decide whether we want to apply that coloring situationally: e.g., if a non-terminating error is promoted to (script)-terminating via Do we also need to color-distinguish between statement-terminating and script-terminating errors? (Though the latter are more easily spotted by coming last in the output.) |
This comment has been minimized.
This comment has been minimized.
|
We can add additional properties to the ErrorRecord type to differentiate terminating vs non-terminating. For script vs statement, it seems the simplest is to output:
|
This comment has been minimized.
This comment has been minimized.
|
Re adding a new property: I've created a new issue: #4781. Re script vs statement: That's a little verbose for the single-line representation we're trying to create here. As a wistful aside: In a world without backward-compatibility constraints, ideally we wouldn't have to deal with the distinction between statement-terminating and script-terminating at all, because there should only be one type of terminating error: the script-terminating type. (If only the documentation were correct...): The nature of the current statement-terminating errors is so severe that it makes no sense to let scripts continue by default. |
This comment has been minimized.
This comment has been minimized.
dragonwolf83
commented
Sep 8, 2017
|
For the one-line, I think the first word should be A key scenario that needs to be considered is logging the output to a file. The output should be easy to parse and won't have color coding to help. Using Statement vs Non-Termination can be differentiated by one of the following: Severity is what SQL Server calls the these types of errors and it makes the most sense. It would probably make the documentation clearer as well because a non-terminating error is not as severe as a terminating error which stops the script. |
This comment has been minimized.
This comment has been minimized.
|
Good points re symmetry with Again, though, I'm worried about verbosity for single-line representations:
Even though I'd say the default view should favor human eyeballs (with still some support for parsing, based on the |
SteveL-MSFT
removed
the
Up-for-Grabs
label
Sep 29, 2017
SteveL-MSFT
added this to Interactive Console
in Strategic Investments
Sep 29, 2017
This comment has been minimized.
This comment has been minimized.
alx9r
commented
Mar 1, 2018
|
FWIW, it seems that currently try
{
throw [System.Exception]::new('message')
}
catch
{
[bool]$_.Exception.WasThrownFromThrowStatement
}outputs |
This comment has been minimized.
This comment has been minimized.
|
You've found an edge case: It works as intended if you throw anything other than a The only exception type you can throw and still have it reflected in Thus, the following 2 commands are equivalent and both output try { throw 'message' } catch { $_.Exception.WasThrownFromThrowStatement }
try { throw [System.Management.Automation.RuntimeException]::new('message') } catch { $_.Exception.WasThrownFromThrowStatement }I agree that throwing an actual exception-type instance should also be reflected in |
This comment has been minimized.
This comment has been minimized.
alx9r
commented
Mar 1, 2018
|
Thanks @mklement0. I opened issue #6288. |
SteveL-MSFT
removed this from the 6.1.0-Consider milestone
Jun 20, 2018
This comment has been minimized.
This comment has been minimized.
|
Perhaps also consider showing the wrapped ErrorRecord or InnerException rather than having the user dig for it. Example of such a case is #8173 |
This comment has been minimized.
This comment has been minimized.
|
It sure would be nice if some form of simplified error output makes it into 6.2. :-) |
This comment has been minimized.
This comment has been minimized.
|
@rkeithhill I agree, but would need some proposals that we can discuss. I played with @mklement0's prototype and made some changes to leverage VT100 escape sequences: https://gist.github.com/SteveL-MSFT/edf969ee676206a47d520a9032dcf6e3 |
This comment has been minimized.
This comment has been minimized.
|
Something I would really love to see is some sort of indication as to what type of error is being shown. Since terminating errors behave pretty differently to non-terminating errors (ignoring -ErrorAction common parameter, etc) I think it would be valuable if we could distinguish the type of error at a glance. |
This comment has been minimized.
This comment has been minimized.
Jaykul
commented
Feb 12, 2019
|
Can we make this a lot easier to extend by just allowing anyone to write a |
This comment has been minimized.
This comment has been minimized.
Jaykul
commented
Feb 12, 2019
|
OK, I had a poke at this, just to provide another approach. function ConvertTo-SimpleErrorView {
[CmdletBinding()]
param(
[System.Management.Automation.ErrorRecord]
$InputObject
)
if ($InputObject.FullyQualifiedErrorId -eq "NativeCommandErrorMessage") {
$InputObject.Exception.Message
} else {
$myinv = $InputObject.InvocationInfo
if ($myinv -and ($myinv.MyCommand -or ($InputObject.CategoryInfo.Category -ne 'ParserError'))) {
# rip off lines that say "At line:1 char:1" (hopefully, in a language agnostic way)
$posmsg = $myinv.PositionMessage -replace "^At line:1 .*[\r\n]+"
# rip off the underline and instead, put >>>markers<<< around the important bit
# we could, instead, set the background to a highlight color?
$pattern = $posmsg -split "[\r\n]+" -match "\+( +~+)\s*" -replace '(~+)', '($1)' -replace '( +)','($1)' -replace '~| ','.'
$posmsg = $posmsg -replace '[\r\n]+\+ +~+'
if ($pattern) {
$posmsg = $posmsg -replace "\+$pattern", '+ $1>>>$2<<<'
}
} else {
$posmsg = ""
}
if ($posmsg -ne "") {
$posmsg = "`n" + $posmsg
}
if ( & { Set-StrictMode -Version 1; $InputObject.PSMessageDetails } ) {
$posmsg = " : " + $InputObject.PSMessageDetails + $posmsg
}
$indent = 4
$width = $host.UI.RawUI.BufferSize.Width - $indent - 2
$originInfo = & { Set-StrictMode -Version 1; $InputObject.OriginInfo }
if (($null -ne $originInfo) -and ($null -ne $originInfo.PSComputerName)) {
$indentString = "+ PSComputerName : " + $originInfo.PSComputerName
$posmsg += "`n"
foreach ($line in @($indentString -split "(.{$width})")) {
if ($line) {
$posmsg += (" " * $indent + $line)
}
}
}
if (!$InputObject.ErrorDetails -or !$InputObject.ErrorDetails.Message) {
$InputObject.Exception.Message + $posmsg + "`n "
} else {
$InputObject.ErrorDetails.Message + $posmsg
}
}
}And then I made a quick demo module, setting the ErrorInstance view to call named functions ... <ExpressionBinding>
<ScriptBlock>
<![CDATA[
if ($formatter = Get-Command "ConvertTo-$($global:ErrorView -replace "View")ErrorView" -ListImported -ErrorAction Ignore -ParameterName InputObject -ParameterType [System.Management.Automation.ErrorRecord]) {
&@($formatter)[0] $_
} else {
ConvertTo-NormalErrorView $_
}
]]>
</ScriptBlock>
</ExpressionBinding>And of course, copying the existing Normal and Category views into And then I wrote a hack of a I'd definitely like to see something like this in core, so we can easily customize error formatting in our profiles without writing format files... Here's my attempt (and it works down to PowerShell 5.x, at least) as a mini module called ErrorView |
SteveL-MSFT
modified the milestones:
Future,
6.3-Consider
Feb 19, 2019
This comment has been minimized.
This comment has been minimized.
GoateePFE
commented
May 31, 2019
|
While we're at it, how about making error text white characters on red background. That would be so much easier to read than dark red on black, especially on a projector. |
This comment has been minimized.
This comment has been minimized.
Kriegel
commented
Jun 4, 2019
|
Why not let the user pass an { Scriptblock } or Function to self define the error formatting and output? |
This comment has been minimized.
This comment has been minimized.
|
While a think a new error view could be helpful (to the point where I had implemented one in a module many years ago, but then I lost that module due to clumsy fingers on my keyboard), I prefer heading towards something smarter. @lzybkr talked about a smarter default view here. That's where my line of thinking tends to go as well. For example, I was thinking about errors today, in particular about how they are presented. In some cases, the text we present is not as clear and straightforward as it could be. In some cases, we show a bunch of extra detail that is not necessary (position, etc.). In all cases, the error is red. We can do better. How do we identify when errors should be presented differently? For PowerShell use errors (an error that occurs from ad-hoc PowerShell use and is clearly an error that came from incorrect use of something in PowerShell, e.g. invoking a command ad-hoc and parameter binding/validation fails, trying to invoke a command that does not exist, and other parameter binder or argument validator errors that occur), or other user errors (permission denied when trying to do something, unable to find a resource because it does not exist, etc., still done through ad-hoc command invocation), position details don't matter, other than perhaps the marker indicating where the error came from in the command that was invoked. For errors that come from a script or module or remote invocation of a job, the script/file position matters. Beyond determining whether or not position should be shown, based on whether or not the command came from ad-hoc use vs running a script, module, job, etc., color matters, to the point where some presenters, myself included, suggest people change their error color so that it's more presentable and easier to read. That general change aside, it would be beneficial for us to show different colors for use errors vs resource not found errors vs access denied errors, or other errors. While this may be over-simplifying things, looking through the Personally I would not apply a different color for terminating errors vs non-terminating errors, because I don't think it adds enough value, and keeping the number of colors used to present errors down to a minimum is important. I would consider displaying something differently for a terminating error that comes from a command, script, or module (i.e. show whether or not the error was terminating in the This approach keeps the number of colors small enough to be manageable (3), and simplifies display of ad-hoc errors vs script errors so that users can work with error messages more easily and have a better chance at knowing at a glance where something came from and what happened. |
This comment has been minimized.
This comment has been minimized.
|
Just stumbled across this one today, wanted to link it to PowerShell/PowerShell-RFC#215 |
This comment has been minimized.
This comment has been minimized.
whereisaaron
commented
Sep 13, 2019
|
Excellent. Pleased to see some movement with the RFC @joeyaiello! I think @dragonwolf83 has the right idea, ie. just display the error without all the junk that buries what you need to know. The RFC starts off great, promising a single line error message. But depressingly the discussion is all about complex extensibility, formatting and |
This comment has been minimized.
This comment has been minimized.
|
@whereisaaron: There are diverse needs to consider. Making error messages simple for end users is one need. Making error messages more detailed for scripters is another. Doing so while at considering tool builders is important. It doesn't mean that is what will be built, but the entire discussion is worthwhile having. |
This comment has been minimized.
This comment has been minimized.
whereisaaron
commented
Sep 13, 2019
|
@KirkMunro sorry, I don't think anyone is - and I wasn't - suggesting taking away the full error object for debuggers, just displaying less of it to interactive shell users by default. The discussion here and on the RFC is very interesting, I read it through, but it has been two years of discussing so far, so I was hoping someone could get to a decision |


mklement0 commentedApr 25, 2017
The currently supported
$ErrorViewvalues are:NormalView- the default, "noisy", multi-line display:CategoryView- a terse, single-line display that doesn't always contain enough information:It would be nice to have another option - e.g.,
ConciseView- that limits output to a single line that contains the immediately relevant information (digging deeper - if needed - is always possible via$Error[0]):Arguably, this kind of display is the most useful to end users when viewed in the console, so perhaps it should be the default.
As an aside: requiring the
$ErrorViewvalues to end in*Viewseems redundant; related: #3644 and #3645.Environment data