go-task/task · error
task: precondition not met
Error message
task: precondition not met
What it means
ErrPreconditionFailed is returned by Executor.areTaskPreconditionsMet when one of a task's `preconditions` shell commands exits non-zero. Preconditions act as guard clauses: each `sh:` snippet is run before the task's commands, its stderr/output is echoed, and if any check fails the whole task is aborted with this error. Unlike errors in commands, a precondition failure means 'this task should not run at all'.
Source
Thrown at precondition.go:14
package task
import (
"context"
"github.com/go-task/task/v3/errors"
"github.com/go-task/task/v3/internal/env"
"github.com/go-task/task/v3/internal/execext"
"github.com/go-task/task/v3/internal/logger"
"github.com/go-task/task/v3/taskfile/ast"
)
// ErrPreconditionFailed is returned when a precondition fails
var ErrPreconditionFailed = errors.New("task: precondition not met")
func (e *Executor) areTaskPreconditionsMet(ctx context.Context, t *ast.Task) (bool, error) {
for _, p := range t.Preconditions {
err := execext.RunCommand(ctx, &execext.RunCommandOptions{
Command: p.Sh,
Dir: t.Dir,
Env: env.Get(t),
})
if err != nil {
if !errors.Is(err, context.Canceled) {
e.Logger.Errf(logger.Magenta, "task: %s\n", p.Msg)
}
return false, ErrPreconditionFailed
}
}
return true, nil
}View on GitHub (pinned to 385e5ad92a)
Solutions
- Run the precondition's sh snippet manually in your shell to see exactly which check fails and why
- Install the missing dependency or set the missing environment variable the check verifies
- Ensure the snippet runs with the same interpreter/environment as task (shell availability, PATH, cwd = task dir)
- If the precondition is no longer relevant, update or remove it in the Taskfile
Example fix
# before (fails when var unset)
preconditions:
- sh: test -n "$API_KEY"
# after
preconditions:
- sh: test -n "$API_KEY"
msg: "API_KEY must be set; run: export API_KEY=..." Defensive patterns
Strategy: try-catch
Validate before calling
// Before running the task, replicate its preconditions yourself:
for _, p := range task.Preconditions {
if err := execext.RunCommand(ctx, &execext.RunCommandOptions{Command: p.Sh, Dir: task.Dir}); err != nil {
return fmt.Errorf("precondition not met: %s", p.Sh)
}
} Try / catch
if err := e.Run(ctx, task, call); err != nil {
if errors.Is(err, precondition.ErrPreconditionFailed) {
log.Printf("skipping %s: preconditions unmet", task.Name)
return nil // or surface a clear user-facing message
}
return err
} Prevention
- Run each precondition `sh:` snippet manually in the target environment before invoking the task
- Give every precondition a `msg:` so failures explain themselves
- Keep precondition checks to simple, dependency-free shell tests (test -n, command -v, test -f)
- Document required env vars/tools in the repo README so new machines satisfy preconditions
When it happens
Trigger: A task declares `preconditions: [{sh: ...}]` and the shell snippet returns a non-zero exit code, e.g. checking for an env var (`sh: '[ -n "$API_KEY" ]'`), a required binary (`command -v docker`), or a service being reachable. Any non-zero status — including the snippet not being parseable — triggers it.
Common situations: Missing environment variables or config files on a new machine; required tools (docker, terraform) not installed or not on PATH; prerequisites service not running; running a task outside the expected directory. Frequently seen after cloning a repo and skipping setup docs.
Related errors
- task: Included Taskfiles can't have dotenv declarations. Ple
- loop var must be a delimiter-separated string, list or a map
- task: You can't set both --download and --offline flags
- task: You can't set both --download and --clear-cache flags
- task: You can't set both --global and --dir
AI-assisted analysis of go-task/task@385e5ad92a (2026-09-05).
Data as JSON: /api/errors/f9801748f07d1110.
Report an issue: GitHub.