> task -v
task: "default" started
task: [default] nginx -p "/Users/posidoni/powx/cicd/nginx" -c ./nginx.conf -T
panic: runtime error: index out of range [-1]
goroutine 1 gp=0x140000021c0 m=10 mp=0x14000386008 [running]:
panic({0x101100d60?, 0x1400051a150?})
/opt/homebrew/opt/go/libexec/src/runtime/panic.go:802 +0x150 fp=0x14000413a50 sp=0x140004139a0 pc=0x10068c4b0
runtime.goPanicIndex(0xffffffffffffffff, 0x36)
/opt/homebrew/opt/go/libexec/src/runtime/panic.go:115 +0x70 fp=0x14000413a90 sp=0x14000413a50 pc=0x100654910
mvdan.cc/sh/v3/interp.(*Runner).builtin(0x14000295b88, {0x10115bdb0, 0x1400017c780}, {0x0, 0x4001}, {0x140004bc620, 0x5}, {0x140003d2550, 0x2, 0x3})
/Users/posidoni/.cache/go/modcache/mvdan.cc/sh/v3@v3.12.0/interp/builtin.go:729 +0x4d70 fp=0x14000414bb0 sp=0x14000413a90 pc=0x1008369e0
mvdan.cc/sh/v3/interp.(*Runner).call(0x14000295b88, {0x10115bdb0, 0x1400017c780}, {0x3d2550?, 0x140?}, {0x140003d2540, 0x3, 0x4})
/Users/posidoni/.cache/go/modcache/mvdan.cc/sh/v3@v3.12.0/interp/runner.go:1031 +0x5a4 fp=0x14000414ca0 sp=0x14000414bb0 pc=0x100841414
mvdan.cc/sh/v3/interp.(*Runner).cmd(0x14000295b88, {0x10115bdb0, 0x1400017c780}, {0x10115ab90, 0x14000312870})
/Users/posidoni/.cache/go/modcache/mvdan.cc/sh/v3@v3.12.0/interp/runner.go:458 +0x1c5c fp=0x140004151f0 sp=0x14000414ca0 pc=0x10083ebcc
mvdan.cc/sh/v3/interp.(*Runner).stmtSync(0x14000295b88, {0x10115bdb0, 0x1400017c780}, 0x14000280180)
/Users/posidoni/.cache/go/modcache/mvdan.cc/sh/v3@v3.12.0/interp/runner.go:340 +0x158 fp=0x14000415290 sp=0x140004151f0 pc=0x10083cdc8
mvdan.cc/sh/v3/interp.(*Runner).stmt(0x14000295b88, {0x10115bdb0, 0x1400017c780}, 0x14000280180)
/Users/posidoni/.cache/go/modcache/mvdan.cc/sh/v3@v3.12.0/interp/runner.go:322 +0x22c fp=0x14000415310 sp=0x14000415290 pc=0x10083cb5c
mvdan.cc/sh/v3/interp.(*Runner).stmts(...)
/Users/posidoni/.cache/go/modcache/mvdan.cc/sh/v3@v3.12.0/interp/runner.go:829
mvdan.cc/sh/v3/interp.(*Runner).Run(0x14000295b88, {0x10115bdb0, 0x1400017c780}, {0x1011583f8, 0x140003d24c0})
/Users/posidoni/.cache/go/modcache/mvdan.cc/sh/v3@v3.12.0/interp/api.go:901 +0x32c fp=0x140004153b0 sp=0x14000415310 pc=0x10083129c
github.com/go-task/task/v3/internal/execext.RunCommand({0x10115bdb0, 0x1400017c780}, 0x140004157b8)
/Users/posidoni/.cache/go/modcache/github.com/go-task/task/v3@v3.45.4/internal/execext/exec.go:80 +0x5a4 fp=0x140004155b0 sp=0x140004153b0 pc=0x1009dd024
github.com/go-task/task/v3.(*Executor).runCommand(0x140001ca420, {0x10115bdb0, 0x1400017c780}, 0x14000332248, 0x140002b4f40?, 0x0?)
/Users/posidoni/.cache/go/modcache/github.com/go-task/task/v3@v3.45.4/task.go:345 +0x578 fp=0x14000415860 sp=0x140004155b0 pc=0x100c1faa8
github.com/go-task/task/v3.(*Executor).RunTask.func1({0x10115bdb0, 0x1400017c780})
/Users/posidoni/.cache/go/modcache/github.com/go-task/task/v3@v3.45.4/task.go:217 +0x680 fp=0x14000415a20 sp=0x14000415860 pc=0x100c1e770
github.com/go-task/task/v3.(*Executor).startExecution(0x140001ca420, {0x10115bdb0, 0x1400017c780}, 0x1006302bc?, 0x14000415b80)
/Users/posidoni/.cache/go/modcache/github.com/go-task/task/v3@v3.45.4/task.go:376 +0x348 fp=0x14000415af0 sp=0x14000415a20 pc=0x100c201e8
github.com/go-task/task/v3.(*Executor).RunTask(0x140001ca420, {0x10115bdb0, 0x1400017c780}, 0x140002b4f40)
/Users/posidoni/.cache/go/modcache/github.com/go-task/task/v3@v3.45.4/task.go:153 +0x188 fp=0x14000415bb0 sp=0x14000415af0 pc=0x100c1dee8
github.com/go-task/task/v3.(*Executor).Run(0x140001ca420, {0x10115bd40, 0x1016b40a0}, {0x14000325d88, 0x1, 0x4})
/Users/posidoni/.cache/go/modcache/github.com/go-task/task/v3@v3.45.4/task.go:87 +0x314 fp=0x14000415c70 sp=0x14000415bb0 pc=0x100c1d9f4
main.run()
/Users/posidoni/.cache/go/modcache/github.com/go-task/task/v3@v3.45.4/cmd/task/task.go:181 +0x740 fp=0x14000415e90 sp=0x14000415c70 pc=0x100c2cb30
main.main()
/Users/posidoni/.cache/go/modcache/github.com/go-task/task/v3@v3.45.4/cmd/task/task.go:23 +0x20 fp=0x14000415f40 sp=0x14000415e90 pc=0x100c2c110
runtime.main()
/opt/homebrew/opt/go/libexec/src/runtime/proc.go:285 +0x278 fp=0x14000415fd0 sp=0x14000415f40 pc=0x100659918
runtime.goexit({})
Description
Thanks for Task — I've introduced it to teams at several companies as a
makereplacement for Go projects.Placing
pipefailinto theshopt:list (instead ofset:, where it belongs) makestaskcrash withpanic: runtime error: index out of range [-1]instead of reporting a helpful error.Minimal reproduction — both of these Taskfiles panic:
Actual behavior: panic with a Go runtime stack trace (full output below).
Expected behavior: a clear, friendly error explaining what is wrong — ideally suggesting that
pipefailbelongs inset:, or at least the same graceful failure that other invalidshoptvalues already produce:pipefailis special because it is a validset -ooption, which hits a different code path in the interpreter: https://github.com/mvdan/sh/blob/b717ad599e17a6975e15a67ed8937bd8d4909146/interp/builtin.go#L793. The root cause therefore appears to be in themvdan/shlibrary, but I think Task should handle it on its side as well — for example by validatingset:/shopt:values when the Taskfile is read.A related question: would it make sense to
recoveraround the interpreter call, so that a library panic surfaces as a regular task error instead of a crash? I have seen panics from the interpreter in several versions. (Discussed below — validation was preferred overrecover.)Full panic output (task 3.45.4, macOS, Apple Silicon)
Resolution: the panic itself was a bug in
mvdan/sh, confirmed and fixed the same day in mvdan/sh@6bd6eb6, and the fix ships with current Task releases — a misplacedpipefailnow fails with a regularshopt: invalid option name "pipefail"error at runtime. Validatingset:/shopt:values when the Taskfile is read (with a hint to move the option to the right list) was favored by the maintainers overrecover— implemented in the follow-up PR #2911.Version
3.45.4
Operating system
macOS (Apple Silicon)
Experiments Enabled
No response
Example Taskfile