{"record":{"id":"b3f0f1be4fb6010b","repo":"hashicorp/terraform","slug":"invalid-credentials-for-s","errorCode":null,"errorMessage":"invalid credentials for %s","messagePattern":"invalid credentials for (.+?)","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/getproviders/http_mirror_source.go","lineNumber":415,"sourceCode":"\nfunc (s *HTTPMirrorSource) errQueryFailed(provider addrs.Provider, err error) error {\n\tif err == context.Canceled {\n\t\t// This one has a special error type so that callers can\n\t\t// handle it in a different way.\n\t\treturn ErrRequestCanceled{}\n\t}\n\treturn ErrQueryFailed{\n\t\tProvider:  provider,\n\t\tWrapped:   err,\n\t\tMirrorURL: s.baseURL,\n\t}\n}\n\nfunc (s *HTTPMirrorSource) errUnauthorized(finalURL *url.URL) error {\n\thostname, err := svchostFromURL(finalURL)\n\tif err != nil {\n\t\t// Again, weird but we'll tolerate it.\n\t\treturn fmt.Errorf(\"invalid credentials for %s\", finalURL)\n\t}\n\n\treturn ErrUnauthorized{\n\t\tHostname: hostname,\n\n\t\t// We can't easily tell from here whether we had credentials or\n\t\t// not, so for now we'll just assume we did because \"host rejected\n\t\t// the given credentials\" is, hopefully, still understandable in\n\t\t// the event that there were none. (If this ends up being confusing\n\t\t// in practice then we'll need to do some refactoring of how\n\t\t// we handle credentials in this source.)\n\t\tHaveCredentials: true,\n\t}\n}\n\nfunc svchostFromURL(u *url.URL) (svchost.Hostname, error) {\n\traw := u.Host\n","sourceCodeStart":397,"sourceCodeEnd":433,"githubUrl":"https://github.com/hashicorp/terraform/blob/c9def3e214014c1188faabfc4a5bde5095139765/internal/getproviders/http_mirror_source.go#L397-L433","documentation":"errUnauthorized() is called on a 401/403; it tries to normalize the final (post-redirect) URL's host with svchostFromURL. If that normalization fails (defensive — the URL was already used for a request) it falls back to this plain error instead of an ErrUnauthorized typed error. So the response was an auth rejection AND the final URL host is unparseable.","triggerScenarios":"Mirror responds 401/403 after redirects to a final URL whose host fails IDNA normalization. Rare, because the request had to succeed enough to get a response; indicates an exotic redirect target or a credentials rejection from an unusual host.","commonSituations":"Redirect from the mirror to a host with characters IDNA rejects, combined with missing/invalid credentials; credentials helper misconfigured for the redirected host.","solutions":["Provide valid credentials for the mirror host in the CLI config.","Fix the redirect target so the final URL host is a normal DNS name.","Confirm the configured credentials token is current and has not expired."],"exampleFix":"# before: no creds, mirror requires auth\nprovider_installation { network_mirror { url = \"https://mirror.local/tf/\" } }\n\n# after\ncredentials \"mirror.local\" { token = \"$MIRROR_TOKEN\" }\nprovider_installation { network_mirror { url = \"https://mirror.local/tf/\" } }","handlingStrategy":"validation","validationCode":"// Ensure credentials exist and the mirror host normalizes before use.\nhost, err := svchost.FromURL(mirrorURL)\nif err != nil { return fmt.Errorf(\"mirror host invalid: %w\", err) }\nif _, err := creds.ForHost(host); err != nil { return err }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Configure credentials for the mirror host in the CLI config.","Avoid redirects to hosts with IDNA-invalid names.","Rotate/verify the token is still valid."],"tags":["credentials","url","mirror","hostname"],"analyzedSha":"c9def3e214014c1188faabfc4a5bde5095139765","analyzedAt":"2026-08-07T15:39:49.278Z","schemaVersion":2},"datasetVersion":"2026-08-07T21:17:07.882Z"}