hashicorp/terraform · error
Failed to retrieve token
Error message
Failed to retrieve token: %s
What it means
Thrown by the manual-token branch of login.go when c.UIInput().Input fails for the token prompt. This is the path where the user pastes a token (as opposed to the OAuth/password flows); the error means the prompt to read the token could not complete, not that the token is invalid. Token validity is checked afterwards via tfe.NewClient.
Solutions
- Set the token directly via `TF_TOKEN_<hostname>` env var or write it to ~/.terraform.d/credentials.tfrc.json.
- Run `terraform login` in a real terminal so the prompt can be read.
- Use the browser OAuth flow instead of manual token entry.
- Ensure stdin is an interactive TTY when manual entry is required.
Example fix
# before: terraform login (token path) with no TTY -> 'Failed to retrieve token'
# after: write the credentials file directly
cat > ~/.terraform.d/credentials.tfrc.json <<EOF
{ "credentials": { "app.terraform.io": { "token": "<token>" } } }
EOF
terraform init Defensive patterns
Strategy: validation
Validate before calling
if !canPrompt() { // see error 637's canPrompt()
return errors.New("no TTY: set TF_TOKEN_<hostname> or write ~/.terraform.d/credentials.tfrc.json")
} Try / catch
token, err := c.UIInput().Input(ctx, opts)
if err != nil {
if !canPrompt() {
return fmt.Errorf("token prompt needs a TTY; set TF_TOKEN_%s or use the OAuth flow: %w", hostname, err)
}
return err
} Prevention
- Provide the token via TF_TOKEN_<hostname> or the credentials file in non-interactive environments.
- Prefer the browser OAuth flow over manual token entry when a TTY is unavailable.
- Check for a TTY before invoking `terraform login` in scripts.
When it happens
Trigger: Non-interactive environment with no TTY; the token prompt was cancelled, empty, or EOF'd; a custom UIInput backend errored on the secret prompt.
Common situations: Running `terraform login` in CI/containers; stdin closed or piped; user aborted at the token prompt; automating login where a TTY is unavailable.
Related errors
- Failed to request password
- Failed to request username
- Token is invalid
- Couldn't create initial workspace
- couldn't read information for cloud run
AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11).
Data as JSON: /api/errors/9c2112e0334f54b0.
Report an issue: GitHub.
Appendix: 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 d32a084675)