hashicorp/terraform · error
no suitable TCP ports (between %d and %d) are available for
Error message
no suitable TCP ports (between %d and %d) are available for the temporary OAuth callback server
What it means
Thrown by listenerForCallback when every TCP port in the host-advertised OAuth callback range is busy after ~1.5x the range size of random attempts. The temporary local OAuth callback server (for the authorization-code flow) could not bind any port, so the OAuth login cannot complete.
Source
Thrown at internal/command/login.go:752
// another.
maxTries := availCount + (availCount / 2)
for tries := 0; tries < maxTries; tries++ {
port := rand.Intn(availCount) + int(minPort)
addr := fmt.Sprintf("127.0.0.1:%d", port)
log.Printf("[TRACE] login: trying %s as a listen address for temporary OAuth callback server", addr)
l, err := net.Listen("tcp4", addr)
if err == nil {
// We use a path that doesn't end in a slash here because some
// OAuth server implementations don't allow callback URLs to
// end with slashes.
callbackURL := fmt.Sprintf("http://localhost:%d/login", port)
log.Printf("[TRACE] login: callback URL will be %s", callbackURL)
return l, callbackURL, nil
}
}
return nil, "", fmt.Errorf("no suitable TCP ports (between %d and %d) are available for the temporary OAuth callback server", minPort, maxPort)
}
func (c *LoginCommand) proofKey() (key, challenge string, err error) {
// Wel use a UUID-like string as the "proof key for code exchange" (PKCE)
// that will eventually authenticate our request to the token endpoint.
// Standard UUIDs are explicitly not suitable as secrets according to the
// UUID spec, but our go-uuid just generates totally random number sequences
// formatted in the conventional UUID syntax, so that concern does not
// apply here: this is just a 128-bit crypto-random number.
uu, err := uuid.GenerateUUID()
if err != nil {
return "", "", err
}
key = fmt.Sprintf("%s.%09d", uu, rand.Intn(999999999))
h := sha256.New()
h.Write([]byte(key))View on GitHub (pinned to c9def3e214)
Solutions
- Free up ports in the advertised range: stop other local servers or stale `terraform login` processes.
- Retry `terraform login` after closing other OAuth callback listeners.
- If self-hosted TFE/Terraform Enterprise, widen the advertised OAuth callback port range in the service description.
- As a workaround, use the token-paste flow or write credentials to the credentials file directly.
Defensive patterns
Strategy: retry
Validate before calling
// Before starting the OAuth flow, probe a candidate callback port in the advertised range.
func freePortIn(minPort, maxPort uint16) (uint16, error) {
for i := 0; i < (int(maxPort)-int(minPort))*3/2; i++ {
p := uint16(rand.Intn(int(maxPort)-int(minPort))) + minPort
l, err := net.Listen("tcp4", fmt.Sprintf("127.0.0.1:%d", p))
if err == nil { l.Close(); return p, nil }
}
return 0, errors.New("no free OAuth callback port")
} Try / catch
l, cb, err := cmd.ListenerForCallback(minPort, maxPort)
if err != nil {
// No ports free — close stale listeners and retry, or fall back to token-paste flow.
return err
} Prevention
- Free ports in the advertised OAuth callback range before running `terraform login`.
- Kill stale `terraform login` processes that may hold callback listeners.
- For self-hosted TFE, advertise a reasonably wide callback port range.
When it happens
Trigger: Produced during `terraform login` OAuth authorization-code flow when net.Listen('tcp4', '127.0.0.1:<port>') fails for every port sampled in [minPort, maxPort]. The port range comes from the host's OAuth service description (minPort/maxPort). Triggered when the range is exhausted by other listeners or the range is tiny/empty.
Common situations: Machine has many services occupying the callback port range; a previous crashed `terraform login` left a callback listener bound; the host advertises a very narrow port range; or another OAuth flow is in progress. Most common on busy dev machines or in containers with limited port availability.
Related errors
- Failed to request username: %s
- Failed to retrieve user account details: %s
- operation timed out
- operation timed out
- Login cancelled
AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07).
Data as JSON: /api/errors/e8bc88ab211c9c4b.
Report an issue: GitHub.