docker/cli · error

error: cannot perform an interactive login from a non-TTY…

Error message

error: cannot perform an interactive login from a non-TTY device

What it means

Thrown by loginUser when either the username or password is missing AND stdin is not a TTY. Without an interactive terminal the CLI cannot prompt for the missing credential, so it refuses rather than hang. This is the classic non-interactive/CI login failure.

Solutions

  1. Provide both credentials non-interactively: 'printf %s "$TOKEN" | docker login -u <user> --password-stdin'.
  2. Run the command in a real interactive TTY if you want prompting.
  3. Use a credential helper or stored credentials to avoid passing secrets at all.

Example fix

# before (in CI)
echo "$TOKEN" | docker login
# after
printf '%s' "$TOKEN" | docker login -u "$DOCKER_USER" --password-stdin
Defensive patterns

Strategy: validation

Validate before calling

// Detect non-TTY stdin and require explicit credentials
if (user == "" || password == "") && !in.IsTerminal() {
    return fmt.Errorf("non-interactive login requires -u and --password-stdin")
}

Prevention

When it happens

Trigger: Running 'echo token | docker login' (no -u/-p) in a script or CI; 'cat file | docker login'; running under mintty/Git Bash where stdin is a pipe not a console (login.go lines 237-238).

Common situations: CI pipelines, cron jobs, non-interactive SSH sessions, Windows mintty/Git Bash pipes, any redirected stdin.

Related errors


AI-assisted analysis of docker/cli@4f84911bfe (2026-08-07). Data as JSON: /api/errors/e1467774b72a1ab7. Report an issue: GitHub.

Appendix: source

Thrown at cli/command/registry/login.go:238

	}

	if err := storeCredentials(dockerCLI.ConfigFile(), authConfig); err != nil {
		return "", err
	}

	return resp.Auth.Status, err
}

func loginUser(ctx context.Context, dockerCLI command.Cli, opts loginOptions, defaultUsername, serverAddress string) (msg string, _ error) {
	// Some links documenting this:
	// - https://code.google.com/archive/p/mintty/issues/56
	// - https://github.com/docker/docker/issues/15272
	// - https://mintty.github.io/ (compatibility)
	// Linux will hit this if you attempt `cat | docker login`, and Windows
	// will hit this if you attempt docker login from mintty where stdin
	// is a pipe, not a character based console.
	if (opts.user == "" || opts.password == "") && !dockerCLI.In().IsTerminal() {
		return "", errors.New("error: cannot perform an interactive login from a non-TTY device")
	}

	// If we're logging into the index server and the user didn't provide a username or password, use the device flow
	if serverAddress == registry.IndexServer && opts.user == "" && opts.password == "" {
		var err error
		msg, err = loginWithDeviceCodeFlow(ctx, dockerCLI)
		// if the error represents a failure to initiate the device-code flow,
		// then we fallback to regular cli credentials login
		if !errors.Is(err, manager.ErrDeviceLoginStartFail) {
			return msg, err
		}
		_, _ = fmt.Fprint(dockerCLI.Err(), "Failed to start web-based login - falling back to command line login...\n\n")
	}

	return loginWithUsernameAndPassword(ctx, dockerCLI, opts, defaultUsername, serverAddress)
}

func loginWithUsernameAndPassword(ctx context.Context, dockerCLI command.Cli, opts loginOptions, defaultUsername, serverAddress string) (msg string, _ error) {

View on GitHub (pinned to 4f84911bfe)