go-task/task · error

no terminal

Error message

no terminal

What it means

ErrNoTerminal is a sentinel error exported by the logger package. The Executor's Logger.Prompt (used for interactive confirmations, e.g. prompts declared with `prompt:` in a task) refuses to ask a question when it cannot read an interactive answer: if AssumeTerm is false and term.IsTerminal() reports that stdin is not a TTY, it returns ErrNoTerminal instead of blocking forever on piped input. Callers such as the Executor translate it into TaskCancelledNoTerminalError, treating the task as cancelled.

Source

Thrown at internal/logger/logger.go:21

import (
	"bufio"
	"io"
	"slices"
	"strconv"
	"strings"

	"github.com/Ladicle/tabwriter"
	"github.com/fatih/color"

	"github.com/go-task/task/v3/errors"
	"github.com/go-task/task/v3/experiments"
	"github.com/go-task/task/v3/internal/env"
	"github.com/go-task/task/v3/internal/term"
)

var (
	ErrPromptCancelled = errors.New("prompt cancelled")
	ErrNoTerminal      = errors.New("no terminal")
)

var (
	attrsReset       = envColor("COLOR_RESET", color.Reset)
	attrsFgBlue      = envColor("COLOR_BLUE", color.FgBlue)
	attrsFgGreen     = envColor("COLOR_GREEN", color.FgGreen)
	attrsFgCyan      = envColor("COLOR_CYAN", color.FgCyan)
	attrsFgYellow    = envColor("COLOR_YELLOW", color.FgYellow)
	attrsFgMagenta   = envColor("COLOR_MAGENTA", color.FgMagenta)
	attrsFgRed       = envColor("COLOR_RED", color.FgRed)
	attrsFgHiBlue    = envColor("COLOR_BRIGHT_BLUE", color.FgHiBlue)
	attrsFgHiGreen   = envColor("COLOR_BRIGHT_GREEN", color.FgHiGreen)
	attrsFgHiCyan    = envColor("COLOR_BRIGHT_CYAN", color.FgHiCyan)
	attrsFgHiYellow  = envColor("COLOR_BRIGHT_YELLOW", color.FgHiYellow)
	attrsFgHiMagenta = envColor("COLOR_BRIGHT_MAGENTA", color.FgHiMagenta)
	attrsFgHiRed     = envColor("COLOR_BRIGHT_RED", color.FgHiRed)
)

View on GitHub (pinned to 385e5ad92a)

Solutions

  1. Run the command with --yes (-y) to auto-approve prompts non-interactively
  2. Run with --assume-terminal (-a) if stdin really is interactive but detection fails (e.g. some CI/PTY setups)
  3. Remove or gate the `prompt:` declaration in the task for non-interactive environments
  4. Restructure the pipeline so task's stdin is a real TTY (e.g. avoid piping into `task`)

Example fix

// before (CI)
run: task deploy
// after
deploy-job:
  runs-on: ubuntu-latest
  steps:
    - run: task deploy --yes
Defensive patterns

Strategy: try-catch

Validate before calling

// Guard in a wrapper around task execution when stdin may not be a TTY (Go)
if term.IsTerminal(int(os.Stdin.Fd())) {
    return runTask(args...) // prompts will work
}
// else run with -y or skip tasks that declare prompt:

Type guard

func isInteractive() bool {
	return term.IsTerminal(int(os.Stdin.Fd()))
}

Try / catch

if err := e.Logger.Prompt(logger.Yellow, p, "n", "y", "yes"); err != nil {
    if errors.Is(err, logger.ErrNoTerminal) {
        return &errors.TaskCancelledNoTerminalError{TaskName: call.Task} // handle non-TTY
    }
    if errors.Is(err, logger.ErrPromptCancelled) { /* user said no */ }
    return err
}

Prevention

When it happens

Trigger: Running a task that declares `prompt:` (or otherwise calls Logger.Prompt) in an environment where stdin is not a terminal: CI pipelines, `task <...> | cat`, output redirection, nohup/daemon contexts, or pipes like `echo y | task ...` — unless the --assume-terminal (-a) flag / AssumeTerm is set or --yes (-y) is used to skip prompts.

Common situations: CI jobs (GitHub Actions, GitLab CI) running destructive tasks guarded by prompts; scripts that pipe or redirect task's stdin; running inside docker exec without -t; cron jobs. Users often hit it after upgrading tasks to add a prompt without updating their automation to pass -y/-a.

Related errors


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