hashicorp/terraform · error

Failed to request username: %s

Error message

Failed to request username: %s

What it means

Thrown by the login command's password-grant flow when the UI input call requesting the username fails. The %s carries the input error (e.g. EOF when input is disabled, or a terminal I/O error). It aborts the interactive username/password OAuth login before contacting the host.

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 c9def3e214)

Solutions

  1. Run `terraform login` in an interactive terminal with a TTY.
  2. Do not pass -input=false for the password-grant login flow.
  3. If non-interactive, prefer the token-based flow: generate a token in the browser and place it in ~/.terraform.d/credentials.tfrc.json manually.
  4. Check that stdin is not redirected/closed when the command runs.

Example fix

// before: non-interactive, input disabled
terraform login -input=false app.terraform.io
// after: interactive TTY
terraform login app.terraform.io
Defensive patterns

Strategy: validation

Validate before calling

// Before running the password-grant login, ensure interactive input is available.
if !ui.InputEnabled() || !term.IsTerminal(int(os.Stdin.Fd())) {
    return errors.New("terraform login requires an interactive terminal; set credentials manually instead")
}

Try / catch

if _, err := cmd.UsernamePrompt(); err != nil {
    // Input unavailable — fall back to manual credentials file or token env var.
    return err
}

Prevention

When it happens

Trigger: Produced when c.UIInput().Input() returns a non-nil error for the 'username' prompt during `terraform login` with a host that advertises the OAuth password grant. Triggered when interactive input is unavailable (non-TTY, input disabled, or stdin closed).

Common situations: Running `terraform login` in a non-interactive environment (CI, container, piped stdin) without a TTY; input explicitly disabled via -input=false; or a custom UI input implementation that errored. The password-grant flow requires interactive prompting.

Related errors


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