You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
ignore_error not working on new built-in cp command #2466
The new built-in cp command to copy a file that may or may not exist, with the ignore_error: true property set on the cmd: scope
Expected cp command errors to be suppressed
cp errors were not suppressed and tasks fail
No change if -f is used or not.
Adding powershell before the cp command works as expected even if the powershell command fails.
This task is just a best-effort file copy for some testing, and some files may not exist for now, and simply suppressing the error is the simplest solution for now.
Example error
task: Failed to run task "dev-plugins-fetch": GetFileAttributesEx C:\tests\config\Essentials.Accounts.json: The system cannot find the file specified.
The error fs.PathError{Op:"CreateFile"...) from os.OpenFile (in u-root function copyRegularFile()) is passed directly back to Task. Task has been implemented to expect an error of type interp.ExitStatus, so it does not handle the error from u-root.
In mvdan/sh/interp/api.go fromHandlerError() windows code will call fatal(error) which then sets e.code to 1, and e.err to the aforementioned error.
Later on, in mvdan/sh/api.go Run() we see that error is now processed:
// Return the first of: a fatal error, a non-fatal handler error, or the exit code.
if err := r.exit.err; err != nil {
return err
}
if code := r.exit.code; code != 0 {
return ExitStatus(code)
}
return nil
and you see that err has priority over code, so, in the windows case, err is returned ... which triggers the failing condition observed in Task. The "code", although set, is actually lost, which is what eventually breaks the Task code.
With that in mind, there are a few ways to fix this problem; have exitStatus:fatal() wrap the error in an ExitStatus error, or change Task so that it also handles other error conditions.
@andreynering or @pd93 do either of you know of the top of you head how to deal with this kind of problem:
func (e *exitStatus) fatal(err error) {
if !e.fatalExit && err != nil {
e.exiting = true
e.fatalExit = true
e.err = err // **** u-root error is directly used here, and Task does not handle that (it looks for interp.ExitStatus)
if e.code == 0 {
e.code = 1
}
}
}
func (e *exitStatus) fromHandlerError(err error) {
if err != nil {
var exit errBuiltinExitStatus
var es ExitStatus
if errors.As(err, &exit) {
*e = exitStatus(exit)
} else if errors.As(err, &es) {
e.err = err // **** task looks for this condition, esp. ExitStatus, which is the case on linux
e.code = uint8(es)
} else {
// **** windows/u-root takes this path
e.fatal(err) // handler's custom fatal error
}
} else {
e.code = 0
}
}
Task seems to be deliberately only enabling the "ignore-error" for interop.ExitStatus errors, which might be sensible (since other errors are probably non-ignorable). So, the problem might need to be solved in the mcdan/sh interp ... specifically in the area identified above, probably by wrapping the err with ExitStatus.
Or, it could be fixed in the coreutils ExecHandler(), by wrapping the error there, before it reaches the above code. I think that could be the better solution.
So, the problem might need to be solved in the mcdan/sh interp ... specifically in the area identified above, probably by wrapping the err with ExitStatus.
@trulede Yeah, wrapping the error is probably the right solution here! Just not sure if on the lib (mvdan/sh) or on our handler.
Activity
trulede commentedon Dec 6, 2025
Works on Linux, not on Windows/Powershell. Seems likely that
errors.As()is the cause, but I don't know why. I don't have a devenv for windows ...task/task.go
Line 222 in 2161f33
It is possible that the error returned from mvdan/sh under windows is not the expected type (i.e. not interp.ExitStatus).
https://github.com/mvdan/sh/blob/7ad4e4310897576a02731b31da97dfebe4a2f9cd/interp/handler.go#L161
trulede commentedon Jan 7, 2026
The error
fs.PathError{Op:"CreateFile"...)fromos.OpenFile(in u-root function copyRegularFile()) is passed directly back to Task. Task has been implemented to expect an error of type interp.ExitStatus, so it does not handle the error from u-root.In mvdan/sh/interp/api.go fromHandlerError() windows code will call fatal(error) which then sets e.code to 1, and e.err to the aforementioned error.
Later on, in mvdan/sh/api.go Run() we see that error is now processed:
and you see that err has priority over code, so, in the windows case, err is returned ... which triggers the failing condition observed in Task. The "code", although set, is actually lost, which is what eventually breaks the Task code.
With that in mind, there are a few ways to fix this problem; have exitStatus:fatal() wrap the error in an ExitStatus error, or change Task so that it also handles other error conditions.
trulede commentedon Jan 7, 2026
@andreynering or @pd93 do either of you know of the top of you head how to deal with this kind of problem:
Task seems to be deliberately only enabling the "ignore-error" for interop.ExitStatus errors, which might be sensible (since other errors are probably non-ignorable). So, the problem might need to be solved in the mcdan/sh interp ... specifically in the area identified above, probably by wrapping the err with ExitStatus.
Or, it could be fixed in the coreutils ExecHandler(), by wrapping the error there, before it reaches the above code. I think that could be the better solution.
andreynering commentedon Jan 8, 2026
@trulede Yeah, wrapping the error is probably the right solution here! Just not sure if on the lib (mvdan/sh) or on our handler.
andreynering commentedon Jan 18, 2026
Proposal in the interpreter repo:
vmaerten commentedon Aug 10, 2026
It should be fixed by #2943 (and mvdan/sh@1e6494c)
Will be included in the next release