**Bug Description** In one of my build targets, I use `sh.Output` to check the output of a command. For example: ```go output, err := sh.Output("command", "--version") ``` But in my case, it's completely normal for "command" not to exist sometimes, so I want to handle that error differently from other failures that `sh.Output` might return. When the command doesn't exist, the underlying `os/exec` code will return an `fs.PathError`, and the idiomatic way to check for that is to use `errors.Is`: ```go if err != nil { if !errors.Is(err, fs.ErrNotExist) { // This is really an error. return err } // File-doesn't-exist is an expected condition that we can handle. } ``` But `errors.Is` returns false for errors returned by `sh.Output`. **What did you do?** As described above, I tried to use `errors.Is` to inspect errors returned by `sh.Output` and other command-executing functions from `sh`. **What did you expect to happen?** I expected `errors.Is` to recognize errors from `sh` functions as any of various common system errors, particularly `fs.ErrNotExist`. **What actually happened?** `errors.Is` fails to acknowledge that any `sh` error is like any other known error. **Environment** - Mage Version: v1.15.0 - OS: Linux **Additional context** This happens because errors in `sh` are constructed using `fmt.Errorf("...%v", err)`. That inserts the value of `err.String()` but does not actually _wrap_ the error, so any additional information about `err` is discarded. Changing it to `fmt.Errorf("...%w", err)` would solve it without affecting any other behavior. Error wrapping was [introduced in Go 1.13](https://go.dev/doc/go1.13#error_wrapping). My workaround for this issue is to inspect the text of the error message instead: ```go if err != nil { if !strings.Contains(err.Error(), "no such file or directory") { // This is really an error return err } // File-doesn't-exist is an expected condition that we can handle. } ```