hashicorp/terraform · error

Failed to retrieve token: %s

Error message

Failed to retrieve token: %s

What it means

Thrown by the browser/UI-based login flow when the UI input call asking the user to paste a generated token fails. The %s carries the input error. Unlike 633/634 this is the token-paste flow (interactiveGetTokenByUI), where the user generates a token in the browser and pastes it at the prompt.

Source

Thrown at internal/command/login.go:644

	// credsCtx might not be set if we're using a mock credentials source
	// in a test, but it should always be set in normal use.
	if credsCtx != nil {
		switch credsCtx.Location {
		case cliconfig.CredentialsViaHelper:
			c.Ui.Output(fmt.Sprintf("Terraform will store the token in the configured %q credentials helper\nfor use by subsequent commands.\n", credsCtx.HelperType))
		case cliconfig.CredentialsInPrimaryFile, cliconfig.CredentialsNotAvailable:
			c.Ui.Output(fmt.Sprintf("Terraform will store the token in plain text in the following file\nfor use by subsequent commands:\n    %s\n", credsCtx.LocalFilename))
		}
	}

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

	token = strings.TrimSpace(token)
	cfg := &tfe.Config{
		Address:  service.String(),
		BasePath: service.Path,
		Token:    token,
		Headers:  make(http.Header),
	}
	client, err := tfe.NewClient(cfg)
	if err != nil {
		diags = diags.Append(fmt.Errorf("Failed to create API client: %s", err))
		return "", diags
	}
	user, err := client.Users.ReadCurrent(context.Background())
	if err == tfe.ErrUnauthorized {
		diags = diags.Append(fmt.Errorf("Token is invalid: %s", err))

View on GitHub (pinned to c9def3e214)

Solutions

  1. Run `terraform login` in an interactive terminal so the token paste prompt can be answered.
  2. Avoid -input=false with `terraform login`.
  3. If non-interactive, skip the command and write the token to ~/.terraform.d/credentials.tfrc.json manually.
  4. Use a credentials helper or TF_TOKEN_<hostname> env var for automation.

Example fix

// manual credentials file (~/.terraform.d/credentials.tfrc.json)
{
  "credentials": {
    "app.terraform.io": { "token": "<your-token>" }
  }
}
Defensive patterns

Strategy: validation

Validate before calling

// Before the token-paste flow, confirm interactive input is possible.
if !ui.InputEnabled() || !term.IsTerminal(int(os.Stdin.Fd())) {
    return errors.New("token paste requires an interactive terminal; write credentials.tfrc.json manually")
}

Try / catch

if _, err := cmd.TokenPrompt(); err != nil {
    // Prompt failed — write the token to the credentials file directly instead.
    return err
}

Prevention

When it happens

Trigger: Produced when c.UIInput().Input() returns a non-nil error for the 'token' (Secret) prompt during `terraform login` on a host using the UI token flow (no password grant, browser launched). Triggered when interactive input is unavailable after the browser step.

Common situations: Non-interactive environment (CI, no TTY, -input=false) attempting the browser token flow; stdin closed; or a custom UI input that errors. The user reached the paste-token prompt but the input read failed.

Related errors


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