Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

-ErrorAction:Stop doesn't work as it should under special conditions. #12848

Closed
ZonderP opened this issue May 30, 2020 · 6 comments
Closed

-ErrorAction:Stop doesn't work as it should under special conditions. #12848

ZonderP opened this issue May 30, 2020 · 6 comments
Labels
Issue-Question ideally support can be provided via other mechanisms, but sometimes folks do open an issue to get a Resolution-Duplicate The issue is a duplicate.

Comments

@ZonderP
Copy link

ZonderP commented May 30, 2020

Since I yesterday reported a different issue with a simple example, I though it would be a good time to finally also report a bug that really annoys me, since it somehow makes weeks of work useless.

Over the last years I spent many days (or even weeks - all in all) on working on something I call colored HTML transcription (and as a side project 'ANSI colored output' - for use in Jenkins).
Colored HTML transcription mainly works like 'Start-Transcript'/'Stop-Transcript' but instead of just logging text, it more or less transfers the console to an html file with all the colors we see on the console.
For this to work as expected I override all the 'Write-' functions (e.g.: 'Write-Information', 'Write-Warning', 'Write-Error' - except 'Write-Output'.)

I write cmdlets in my modules usually in a way, that they use 'Write-Error', when I consider something to be an error, thus giving the users the possibility to decide for themselves, if those errors should be terminating or not by calling them either with '-ErrorAction:Stop' or not so.

My cmdlets in my modules serve mainly for automated testing, so it is often desired, that a test fails, if an error occurs and thus many of those cmdlets are called with '-ErrorAction:Stop'.
And for automated testing we used to use 'Colored HTML transcription', because for human testers it is very convenient to see colors in transcript files which got produced for test suites which run hundreds of tests over night to immediately see errors and warnings and hints.
But we had to stop to make use of this nice feature, because at some point I found out, that the very important feature of 'auto terminating' a single test with 'Failed' in case of an error didn't work under some circumstances, because of the bug, where -ErrorAction:Stop' just doesn't work.

As a side note:
The bug is easily reproducible on 7.0.1 as well as on 5.1.

Steps to reproduce

Overwrite 'Write-Error' in a module the way it can be found in many examples on the Internet and I think also in the 'Windows PowerShell Cookbook' by 'O'Reilly' (steppablePipeline).
The overwrite just may use again the original 'Microsoft.PowerShell.Utility\Write-Error'.
In that same module write a simple cmdlet called like 'Test-WriteErrorInOverloadModule' which does nothing else then call 'Write-Error' with some message.
Then in some other module write a simple cmdlet called like 'Test-WriteErrorInOtherModule' which also just calls 'Write-Error' with some message.

In the module where the 'Write-Error' overwrite is defined, also add a function which replaces the original 'Write-Error' cmdlet with the 'Overwrite'.

Now call the function which does the 'Write-Error' replacement and then call:
'Test-WriteErrorInOverloadModule -ErrorAction:Stop' within a try/catch
and then call 'Test-WriteErrorInOtherModule -ErrorAction:Stop' withing a try/catch and see what happens!
The first one will go to the catch block, but the second one not!

Expected behavior

Also the call to 'Test-WriteErrorInOtherModule -ErrorAction:Stop' should go to the catch block.

Actual behavior

The call to 'Test-WriteErrorInOtherModule -ErrorAction:Stop' doesn't make the error thrown within that function to be a terminating error as expected.

Environment data

Name Value


PSVersion 7.0.1
PSEdition Core
GitCommitId 7.0.1
OS Microsoft Windows 6.1.7601 Service Pack 1
Platform Win32NT
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0…}
PSRemotingProtocolVersion 2.3
SerializationVersion 1.1.0.1
WSManStackVersion 3.0

I'm quite sure, that some guys here are aware of that problem, because when I tried to find a solution for it back then some months ago - I stumbled over dozens of Powershell 'Error-Handling' related issues and really very long discussions on this topic here on this Powershell GitHub where I also found indications, that this is a real problem that - depending from where called, the behavior might be different.
If you ask me - this is a severe issue, because if you cannot rely on something that important to work the same way independently of some preconditions, you really loose a lot of trust.

Since this bug is not that easy to reproduce, I attached a zip file with 2 modules where everything already is prepared, so that you do not have to write those before-mentioned cmdlets yourself.
Just call the script 'Check.ps1' (located in the 'WriteErrorOverloadModule' base directory) and see what happens.

If someone would know of a workaround to overcome this problem, I would very much appreciate if you could give me hints how to do so.

PoSh Example for Write-Error overload problem.zip

@ZonderP ZonderP added the Issue-Question ideally support can be provided via other mechanisms, but sometimes folks do open an issue to get a label May 30, 2020
@vexx32
Copy link
Collaborator

vexx32 commented May 30, 2020

This is a known issue, but fixing it may break a lot of existing code intentionally or unintentionally built expecting the current behaviour.

See #4568 and @KirkMunro's RFC which would need to be accepted before we can accept any fixes for this problem: PowerShell/PowerShell-RFC#221

This is a bit of a more specific case, it seems, but the symptoms are the same as #4568 ultimately; please add anything more that is not already mentioned in that issue into that thread. I'm marking this one as duplicate for now, though. 🙂

@vexx32 vexx32 added the Resolution-Duplicate The issue is a duplicate. label May 30, 2020
@ZonderP
Copy link
Author

ZonderP commented May 31, 2020

From my understanding I have to disagree that this issue is a duplicate of #4568.
That other issue is about execution preference variables not being transferred to another scope, whereas this issue is about the 'ErrorAction' parameter passed in to a cmdlet defined in another scope not being considered.

There is - in my understanding - a slight chance, that there is an overlap, but from what I read in that other issue's conversation, a parameter like 'ErrorAction' will internally change the execution preference variable 'ErrorActionPreference' in that other scope if it happens that the called cmdlet is in another scope than the callee, but my described issue has really nothing to do with transferring such an execution preference variable to another scope.

I completely understand that fixing #4568 has the potential to break a lot of existing code.

But this ticket is on one hand about something different and on the other hand could have chances to be fixed.

Only because symptoms are somewhat the same does not justify that issues are the same.

@vexx32
Copy link
Collaborator

vexx32 commented May 31, 2020

I agree the reproduction here is a little different, but given that we still are, ultimately, invoking script module functions in both cases, the fact that one is a proxy command for the original cmdlet seems to be a lesser detail.

In both cases, the expected behaviour (inheriting the -ErrorAction preference setting) is lost as soon as a separate script module's code is called.

I would be surprised if there is a second cause for the same issue.

@ZonderP
Copy link
Author

ZonderP commented May 31, 2020

Yes, you're right, I missed an important point:
In my example script I call 'Test-WriteErrorInSomeModule' with the 'ErrorAction:Stop' parameter,
but then the call to Write-Error is not using '-ErrorAction:$ErrorActionPreference', but instead relies on inheritance.
Just to give me some hope:
Would a work-around be that I write my function 'Write-ErrorInternal' as a binary module function?

@vexx32
Copy link
Collaborator

vexx32 commented May 31, 2020

From what I understand, that should work, yeah.

@ghost
Copy link

ghost commented Jun 1, 2020

This issue has been marked as duplicate and has not had any activity for 1 day. It has been closed for housekeeping purposes.

@ghost ghost closed this as completed Jun 1, 2020
This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Issue-Question ideally support can be provided via other mechanisms, but sometimes folks do open an issue to get a Resolution-Duplicate The issue is a duplicate.
Projects
None yet
Development

No branches or pull requests

2 participants