Skip to content

fix: report all dependency failures instead of only the first - #3074

Open
intertermux-code wants to merge 2 commits into
go-task:mainfrom
intertermux-code:fix/3050-join-parallel-dep-errors
Open

intertermux-code wants to merge 2 commits into
go-task:mainfrom
intertermux-code:fix/3050-join-parallel-dep-errors

Conversation

@intertermux-code

Copy link
Copy Markdown

When dependencies run in parallel without failfast, every dependency runs to completion, but errgroup.Wait() only surfaces the first error — any other failures were silently dropped, leaving the user with no idea that more than one dep failed.

Each goroutine now records its error under a mutex, and runDeps returns errors.Join(errs...) so a single run shows every failing dependency. Failfast behaviour is unchanged: it still cancels and returns the first error.

Added TestParallelDepsReportAllFailures with a testdata/deps_fail Taskfile containing two failing deps; it fails without the fix (only one failure surfaced) and passes with it. Full go test ./... is green.

Fixes #3050.

When dependencies run in parallel without failfast, every dep runs to
completion, but errgroup.Wait only surfaced the first error - the rest
were silently dropped. Collect each dep's failure and return them
joined so a single run shows everything that went wrong.
@intertermux-code

Copy link
Copy Markdown
Author

Bumping this one — it's been a week, happy to rework if the design needs it.

@vmaerten vmaerten self-assigned this Nov 1, 2026
@vmaerten
vmaerten self-requested a review November 1, 2026 14:48

@vmaerten vmaerten left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks !

The approach is right, one thing to fix before merging: the order of the joined errors currently depends on which dep finishes first, and #3050 explicitly asks for a deterministic message.

The suggestions below collect the errors by index instead, so they always come out in declaration order.
They depend on each other, so please apply them as a single batch, and add the small Join wrapper to errors/errors.go.
With the order fixed, the test could also assert the exact message instead of two Contains.

Comment thread task.go Outdated
if failfast {
return err
}
return stderrors.Join(errs...)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

errors as you aliased to stderrors cannot be imported.
Please use github.com/go-task/task/v3/errors

Comment thread task.go
Comment on lines +342 to 346
if !failfast && err != nil {
mu.Lock()
errs = append(errs, err)
mu.Unlock()
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if !failfast && err != nil {
mu.Lock()
errs = append(errs, err)
mu.Unlock()
}
errs[i] = err

Collect parallel dep errors by index instead of completion order, so the
joined message is deterministic. Use the repo's errors package (with a new
Join wrapper) instead of stdlib errors, which depguard forbids. Strengthen
the test to assert the exact joined message.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Report all failed parallel tasks, not just one

2 participants