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

  1. Run the precondition's sh snippet manually in your shell to see exactly which check fails and why
  2. Install the missing dependency or set the missing environment variable the check verifies
  3. Ensure the snippet runs with the same interpreter/environment as task (shell availability, PATH, cwd = task dir)
  4. 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

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


AI-assisted analysis of go-task/task@385e5ad92a (2026-09-05). Data as JSON: /api/errors/f9801748f07d1110. Report an issue: GitHub.