hashicorp/terraform · error · ErrUnauthorized
invalid credentials for
Error message
invalid credentials for %s
What it means
`errUnauthorized` tries to derive a `svchost.Hostname` from the final (post-redirect) URL for the `ErrUnauthorized` payload. If that conversion fails — an unusual but tolerated case — it falls back to this plain error message naming the final URL. It is a defensive fallback so the auth-failure path still returns a useful error.
Solutions
- Review the redirect chain (`curl -IL`) that leads to the 401/403 and ensure the final host is a normal DNS hostname.
- Configure correct credentials for the mirror hostname.
- Avoid mirrors that redirect to IP-literal or otherwise unusual hosts.
Example fix
// before: redirect to IP literal triggers fallback https://mirror.local -> 302 -> https://10.0.0.1/ -> 401 // after: mirror serves directly under a DNS hostname https://mirror.local/hashicorp/aws/index.json -> 401 // still unauthorized, // but ErrUnauthorized now carries a real hostname for diagnostics
Defensive patterns
Strategy: try-catch
Validate before calling
// Pre-validate the final URL host is a service hostname
if _, err := svchost.FromString(finalURL.Hostname()); err != nil {
log.Printf("[WARN] final URL host %q not a service hostname; using raw URL in error", finalURL)
} Type guard
// finalURLHasValidHost narrows post-redirect URLs
func finalURLHasValidHost(u *url.URL) bool {
_, err := svchost.FromString(u.Hostname())
return err == nil
} Try / catch
hostname, err := svchostFromURL(finalURL)
if err != nil {
// still return an unauthorized error, just without a structured hostname
return ErrUnauthorized{Hostname: "", HaveCredentials: true}
} Prevention
- Avoid mirrors that redirect to IP literals or unusual hosts.
- Validate redirect targets in the mirror's reverse proxy.
- Test the redirect chain with `curl -IL`.
When it happens
Trigger: A 401/403 response is being formatted; `svchostFromURL(finalURL)` returns an error; fallback at http_mirror_source.go:415.
Common situations: Mirror redirected to a URL with a host `svchost` cannot parse (e.g. an IP literal, an empty host, or an unusual scheme); exotic redirect through a non-DNS hostname.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- too many redirects
- error retrieving state
- error uploading state
- failed to determine request credentials
- failed to upload part
AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11).
Data as JSON: /api/errors/b3f0f1be4fb6010b.
Report an issue: GitHub.
Appendix: source
Thrown at internal/getproviders/http_mirror_source.go:415
func (s *HTTPMirrorSource) errQueryFailed(provider addrs.Provider, err error) error {
if err == context.Canceled {
// This one has a special error type so that callers can
// handle it in a different way.
return ErrRequestCanceled{}
}
return ErrQueryFailed{
Provider: provider,
Wrapped: err,
MirrorURL: s.baseURL,
}
}
func (s *HTTPMirrorSource) errUnauthorized(finalURL *url.URL) error {
hostname, err := svchostFromURL(finalURL)
if err != nil {
// Again, weird but we'll tolerate it.
return fmt.Errorf("invalid credentials for %s", finalURL)
}
return ErrUnauthorized{
Hostname: hostname,
// We can't easily tell from here whether we had credentials or
// not, so for now we'll just assume we did because "host rejected
// the given credentials" is, hopefully, still understandable in
// the event that there were none. (If this ends up being confusing
// in practice then we'll need to do some refactoring of how
// we handle credentials in this source.)
HaveCredentials: true,
}
}
func svchostFromURL(u *url.URL) (svchost.Hostname, error) {
raw := u.Host
View on GitHub (pinned to d32a084675)