HCP Terraform "terraform login" 401 Unauthorized in CI
HCP Terraform returned 401 Unauthorized. The request reached the API but the token was not accepted: it was blank, expired, revoked, or malformed. The host is up; the credential is the problem.
What this error means
A step that hits the HCP Terraform API (or a non-interactive terraform login flow) fails with "401 Unauthorized" or "Invalid token". Public unauthenticated calls behave differently, so it is not a network issue.
Error: Failed to request discovery document: 401 Unauthorized
There was a problem with the API token used to authenticate to app.terraform.io.Common causes
The token is expired or revoked
User and team tokens can expire or be revoked; a revoked token still reaches the API but is rejected with 401.
The secret was never injected
The CI step ran without the token variable set, so an empty or default value was sent and rejected.
How to fix it
Regenerate and re-inject the token
- Create a fresh API token in HCP Terraform.
- Update the CI secret with the new value.
- Expose it as
TF_TOKEN_app_terraform_io(or the credentials file) in the step.
env:
TF_TOKEN_app_terraform_io: ${{ secrets.TF_API_TOKEN }}Confirm the secret is actually set
A 401 with an obviously empty token usually means the secret name is wrong or the job lacks access to it. Verify the secret exists and the step can read it.
How to prevent it
- Rotate HCP Terraform tokens on a schedule and update the secret in one place.
- Prefer team tokens for pipelines so a departing user does not break CI.
- Fail fast if the token variable is empty before running Terraform.