hashicorp/terraform · error

the request failed, please try again later

Error message

the request failed, please try again later%s

What it means

Companion to error 944: returned by maxRetryErrorHandler when numTries == 1, i.e. the very first attempt failed with a retryable condition and there were no additional retries. Same trailing detail format. Indicates a single-shot failure rather than an exhausted retry budget.

Solutions

  1. Set TF_REGISTRY_DISCOVERY_RETRY to a positive value to enable retries.
  2. Investigate the trailing error: status code points to registry issue, raw error points to network/TLS.
  3. Retry the command manually once to rule out a one-off blip.
  4. Confirm the registry hostname resolves and is reachable from the host.

Example fix

// before
Error: the request failed, please try again later: connection refused
// after
$ export TF_REGISTRY_DISCOVERY_RETRY=5
$ terraform init
Defensive patterns

Strategy: retry

Type guard

// Detect a single-shot failure (no retries).
func isSingleShotFailure(err error) bool {
    return err != nil && strings.Contains(err.Error(), "the request failed,")
}

Try / catch

// On single-shot failure, enable retries and retry once.
if strings.Contains(err.Error(), "the request failed,") {
    if os.Getenv("TF_REGISTRY_DISCOVERY_RETRY") == "" {
        os.Setenv("TF_REGISTRY_DISCOVERY_RETRY", "5")
    }
    return retry()
}

Prevention

When it happens

Trigger: RetryMax is 0 (no retries configured) or the first response was a hard failure not qualifying for additional attempts; the handler is invoked with numTries=1.

Common situations: TF_REGISTRY_DISCOVERY_RETRY unset and the first request hit a 5xx or transport error; environment with retry explicitly disabled; immediate DNS or connection refused.

Related errors


AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11). Data as JSON: /api/errors/72300f713691d7ae. Report an issue: GitHub.

Appendix: source

Thrown at internal/getproviders/registry_client.go:493

	}

	// Additional error detail: if we have a response, use the status code;
	// if we have an error, use that; otherwise nothing. We will never have
	// both response and error.
	var errMsg string
	if resp != nil {
		errMsg = fmt.Sprintf(": %s returned from %s", resp.Status, HostFromRequest(resp.Request))
	} else if err != nil {
		errMsg = fmt.Sprintf(": %s", err)
	}

	// This function is always called with numTries=RetryMax+1. If we made any
	// retry attempts, include that in the error message.
	if numTries > 1 {
		return resp, fmt.Errorf("the request failed after %d attempts, please try again later%s",
			numTries, errMsg)
	}
	return resp, fmt.Errorf("the request failed, please try again later%s", errMsg)
}

// HostFromRequest extracts host the same way net/http Request.Write would,
// accounting for empty Request.Host
func HostFromRequest(req *http.Request) string {
	if req.Host != "" {
		return req.Host
	}
	if req.URL != nil {
		return req.URL.Host
	}

	// this should never happen and if it does
	// it will be handled as part of Request.Write()
	// https://cs.opensource.google/go/go/+/refs/tags/go1.18.4:src/net/http/request.go;l=574
	return ""
}

View on GitHub (pinned to d32a084675)