Error on non-zero exit statuses#13515
Conversation
|
The problem with this is that programs often exit with a non-zero exit code even when they exit successfully. Some programs expect to be terminated by Ctrl-C. I think throwing errors in all these cases might produce too much noise. We used to have a config setting for throwing errors on non-zero exit code, but I kept it off because it was too annoying. |
I just stumbled across this PR, and I'd be curious what exactly made this annoying. I think for exit codes > 0, you want to stop execution of a script, but don´t want a scary/annoying error message for your interactive use case every time you cancel I think the best way to get out of this is do define a specific |
|
I don't remember the details, but the Sophia's article highlights the point well. E.g., after running Although, now it seems that code stops executing when encountering a non-zero exit code, in which case you probably do want to have an error, so the suggestion of having a separate |
@IanManske is this something you'd be interested in working on? |
Yes, this is what I was thinking as well. I think it should not show by default in the REPL, but I would still like it to be configurable. So, I was wondering how to best structure the config, but I think I have a decent idea now. I'll have time on the weekend to hopefully knock this PR out. |
|
Making the error showing / not showing in a REPL configurable sounds OK to me, but I wouldn't make stopping the execution in a script configurable because semantics shouldn't depend on the config. This might not be honored in 100% of the cases currently, but IMO we should strive to keep Nushell's execution as deterministic as possible. |
|
One thing to consider is whether we want different behavior for the trailing pipeline position vs. for a pipeline element? Is the assumption correct that when you want to pipe things you want to probably handle the exit code vs at the last part of a statement where it may be a result in of itself? |
|
@sholderbach Maybe others in this thread feel differently, but I struggle a bit to understand the situation you are describing. Could you maybe give one or two examples with code? :) |
Our current code structure makes it impossible to check the exit codes of pipeline elements besides the last, so this PR only checks the trailing element's exit code. One exception is if a command has to collect it's input, and the previous command was an external command. In that case, the exit code is checked as well. |
My gut feeling was that when comparing a) or b) # a)
foo | may-fail
# b)
foo | may-fail | barthat the example b) encodes more of an expectation that things are designed to work together explicitly, so an unhandled exit code presents a true error even in the repl. While a) may present an error in the context of a script the semantics are less clear cut for the repl. But as @IanManske mentioned that is not the primary focus of the current logic
In that sense for b) the handling is inverse that only erroring when explicitly asked for through collect.
|
|
Thanks for the explanation @sholderbach
That is a bit unfortunate. At least for me that will mean that many errors will go unnoticed. But nothing that can be done about this in the short term I guess. |
|
How does this PR work on non-zero exit codes that are not errors like mentioned here https://www.sophiajt.com/exit-codes/? |
|
This PR makes it so that nonzero exit codes are treated as errors, so an error would be triggered in that example. In interactive mode / the REPL, no error message will be displayed by default though. If a non-zero exit code needs to be ignored/caught in, e.g., a script, then |
|
I'm ok with this PR as long as I don't get an error every time I run |
|
Ok, let's see how this goes. |
# Description Fixes a bug in the IR for `try` to match that of the regular evaluator (continuing from #13515): ```nushell # without IR: try { ^false } catch { 'caught' } # == 'caught' # with IR: try { ^false } catch { 'caught' } # error, non-zero exit code ``` In this PR, both now evaluate to `caught`. For the implementation, I had to add another instruction, and feel free to suggest better alternatives. In the future, it might be possible to get rid of this extra instruction. # User-Facing Changes Bug fix, `try { ^false } catch { 'caught' }` now works in IR.
@IanManske Is this still the case? I'm currently using nushell 0.98.0 in a terminal, and sure enough, Is there a config setting that I'm missing? Edit: disregard, just read the changelog. There are new config settings |
|
@wthueb Glad you found the setting. I just made a PR to highlight this in the release notes: nushell/nushell.github.io#1562 |
|
This option MUST be false without config value |
That's what the release notes are for. Nushell is still pre 1.0, so it is expected for there to be occansional breaking changes. Anyways, I wouldn't be against making false the default value for REPL sessions (without config). |
|
#13873 needs to be cleaned up for |

Description
This PR makes it so that non-zero exit codes and termination by signal are treated as a normal
ShellError. Currently, these are silent errors. That is, if an external command fails, then it's code block is aborted, but the parent block can sometimes continue execution. E.g., see #8569 and this example:Before this would give:
Now, this shows an error:
This PR fixes #12874, fixes #5960, fixes #10856, and fixes #5347. This PR also partially addresses #10633 and #10624 (only the last command of a pipeline is currently checked). It looks like #8569 is already fixed, but this PR will make sure it is definitely fixed (fixes #8569).
User-Facing Changes
catchblock may now have anexit_codecolumn containing the integer exit code if the error was due to an external command.display_errors.exit_codeanddisplay_errors.termination_signal, which determine whether an error message should be printed in the respective error cases. For non-interactive sessions, these are set totrue, and for interactive sessionsdisplay_errors.exit_codeis false (via the default config).Tests
Added a few tests.
After Submitting
do -csince this will be the default behavior everywhere.$env.LAST_EXIT_CODE(it's buggy).