{"record":{"id":"e8bc88ab211c9c4b","repo":"hashicorp/terraform","slug":"no-suitable-tcp-ports-between-d-and-d-are-avai","errorCode":null,"errorMessage":"no suitable TCP ports (between %d and %d) are available for the temporary OAuth callback server","messagePattern":"no suitable TCP ports \\(between (.+?) and (.+?)\\) are available for the temporary OAuth callback server","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/command/login.go","lineNumber":752,"sourceCode":"\t// another.\n\tmaxTries := availCount + (availCount / 2)\n\n\tfor tries := 0; tries < maxTries; tries++ {\n\t\tport := rand.Intn(availCount) + int(minPort)\n\t\taddr := fmt.Sprintf(\"127.0.0.1:%d\", port)\n\t\tlog.Printf(\"[TRACE] login: trying %s as a listen address for temporary OAuth callback server\", addr)\n\t\tl, err := net.Listen(\"tcp4\", addr)\n\t\tif err == nil {\n\t\t\t// We use a path that doesn't end in a slash here because some\n\t\t\t// OAuth server implementations don't allow callback URLs to\n\t\t\t// end with slashes.\n\t\t\tcallbackURL := fmt.Sprintf(\"http://localhost:%d/login\", port)\n\t\t\tlog.Printf(\"[TRACE] login: callback URL will be %s\", callbackURL)\n\t\t\treturn l, callbackURL, nil\n\t\t}\n\t}\n\n\treturn nil, \"\", fmt.Errorf(\"no suitable TCP ports (between %d and %d) are available for the temporary OAuth callback server\", minPort, maxPort)\n}\n\nfunc (c *LoginCommand) proofKey() (key, challenge string, err error) {\n\t// Wel use a UUID-like string as the \"proof key for code exchange\" (PKCE)\n\t// that will eventually authenticate our request to the token endpoint.\n\t// Standard UUIDs are explicitly not suitable as secrets according to the\n\t// UUID spec, but our go-uuid just generates totally random number sequences\n\t// formatted in the conventional UUID syntax, so that concern does not\n\t// apply here: this is just a 128-bit crypto-random number.\n\tuu, err := uuid.GenerateUUID()\n\tif err != nil {\n\t\treturn \"\", \"\", err\n\t}\n\n\tkey = fmt.Sprintf(\"%s.%09d\", uu, rand.Intn(999999999))\n\n\th := sha256.New()\n\th.Write([]byte(key))","sourceCodeStart":734,"sourceCodeEnd":770,"githubUrl":"https://github.com/hashicorp/terraform/blob/c9def3e214014c1188faabfc4a5bde5095139765/internal/command/login.go#L734-L770","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// Before starting the OAuth flow, probe a candidate callback port in the advertised range.\nfunc freePortIn(minPort, maxPort uint16) (uint16, error) {\n    for i := 0; i < (int(maxPort)-int(minPort))*3/2; i++ {\n        p := uint16(rand.Intn(int(maxPort)-int(minPort))) + minPort\n        l, err := net.Listen(\"tcp4\", fmt.Sprintf(\"127.0.0.1:%d\", p))\n        if err == nil { l.Close(); return p, nil }\n    }\n    return 0, errors.New(\"no free OAuth callback port\")\n}","typeGuard":null,"tryCatchPattern":"l, cb, err := cmd.ListenerForCallback(minPort, maxPort)\nif err != nil {\n    // No ports free — close stale listeners and retry, or fall back to token-paste flow.\n    return err\n}","preventionTips":["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."],"tags":["terraform","login","oauth","network","ports"],"analyzedSha":"c9def3e214014c1188faabfc4a5bde5095139765","analyzedAt":"2026-08-07T15:39:49.278Z","schemaVersion":2},"datasetVersion":"2026-08-07T21:17:07.882Z"}