hashicorp/terraform · error

Failed to request username

Error message

Failed to request username: %s

What it means

Thrown by the password-grant login flow in internal/command/login.go when c.UIInput().Input fails for the username prompt. UIInput abstracts the interactive prompt (CLI, mock, etc.); an error here means the prompt itself could not be issued or read, not that the credentials are wrong. Common when the process has no usable TTY.

Solutions

  1. Provide credentials non-interactively: set a `TF_TOKEN_<hostname>` environment variable, or write the token to the credentials file (~/.terraform.d/credentials.tfrc.json).
  2. Run `terraform login` in a real interactive terminal (allocate a TTY).
  3. If automating, use the OAuth flow triggered by visiting the printed URL rather than the username/password prompt.
  4. Ensure stdin is a TTY and not redirected when interactive login is required.

Example fix

# before: terraform login run in CI with no TTY -> 'Failed to request username'

# after: provide the token out-of-band
export TF_TOKEN_app_terraform_io="<token>"
terraform init
Defensive patterns

Strategy: validation

Validate before calling

// Skip the interactive login path entirely when no TTY is present.
import "os"

func canPrompt() bool {
    fi, err := os.Stdin.Stat()
    if err != nil {
        return false
    }
    return (fi.Mode() & os.ModeCharDevice) != 0
}

if !canPrompt() {
    return errors.New("no TTY: set TF_TOKEN_<hostname> or populate ~/.terraform.d/credentials.tfrc.json instead of 'terraform login'")
}

Try / catch

username, err := c.UIInput().Input(ctx, opts)
if err != nil {
    if !canPrompt() {
        return fmt.Errorf("login requires a TTY; set TF_TOKEN_%s or run in an interactive terminal: %w", hostname, err)
    }
    return err
}

Prevention

When it happens

Trigger: Running `terraform login` in a non-interactive environment (CI, container, pipe) with no TTY; the UIInput backend errored (EOF on stdin, cancelled context); a custom UIInput implementation returned an error.

Common situations: CI/CD pipelines or Docker runs that invoke `terraform login` instead of providing a token out-of-band; stdin redirected from /dev/null or a closed pipe; interrupted prompt (Ctrl-C/SIGINT).

Related errors


AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11). Data as JSON: /api/errors/05067293de9581b6. Report an issue: GitHub.

Appendix: source

Thrown at internal/command/login.go:552

func (c *LoginCommand) interactiveGetTokenByPassword(hostname svchost.Hostname, credsCtx *loginCredentialsContext, clientConfig *disco.OAuthClient) (*oauth2.Token, tfdiags.Diagnostics) {
	var diags tfdiags.Diagnostics

	confirm, confirmDiags := c.interactiveContextConsent(hostname, disco.OAuthOwnerPasswordGrant, credsCtx)
	diags = diags.Append(confirmDiags)
	if !confirm {
		diags = diags.Append(errors.New("Login cancelled"))
		return nil, diags
	}

	c.Ui.Output("\n---------------------------------------------------------------------------------\n")
	c.Ui.Output("Terraform must temporarily use your password to request an API token.\nThis password will NOT be saved locally.\n")

	username, err := c.UIInput().Input(context.Background(), &terraform.InputOpts{
		Id:    "username",
		Query: fmt.Sprintf("Username for %s:", hostname.ForDisplay()),
	})
	if err != nil {
		diags = diags.Append(fmt.Errorf("Failed to request username: %s", err))
		return nil, diags
	}
	password, err := c.UIInput().Input(context.Background(), &terraform.InputOpts{
		Id:     "password",
		Query:  fmt.Sprintf("Password for %s:", hostname.ForDisplay()),
		Secret: true,
	})
	if err != nil {
		diags = diags.Append(fmt.Errorf("Failed to request password: %s", err))
		return nil, diags
	}

	oauthConfig := &oauth2.Config{
		ClientID: clientConfig.ID,
		Endpoint: clientConfig.Endpoint(),
		Scopes:   clientConfig.Scopes,
	}
	token, err := oauthConfig.PasswordCredentialsToken(context.Background(), username, password)

View on GitHub (pinned to d32a084675)