hashicorp/terraform · error

failed to parse address URL

Error message

failed to parse address URL: %s

What it means

Thrown by the HTTP backend when url.Parse(address) returns an error. The address string was non-empty but malformed enough that Go's net/url rejects it (e.g., control characters, missing scheme with invalid characters, or an unparseable URL).

Solutions

  1. Inspect the address for stray whitespace, newlines, or control characters and remove them.
  2. Ensure the address includes a scheme (http:// or https://).
  3. Print the resolved address before terraform runs to catch interpolation bugs.
  4. Use trimprefix/trimsuffix/trimspace on the variable producing the URL.

Example fix

// before
address = " ${var.state_url}"   # leading space
// after
address = trimspace(var.state_url)
Defensive patterns

Strategy: validation

Validate before calling

address := strings.TrimSpace(rawAddress)
if address == "" {
    return fmt.Errorf("address is empty")
}
u, err := url.Parse(address)
if err != nil {
    return fmt.Errorf("address is not a valid URL: %w", err)
}
if u.Scheme != "http" && u.Scheme != "https" {
    return fmt.Errorf("address must use http or https")
}

Type guard

func isValidHTTPURL(s string) bool {
    u, err := url.Parse(strings.TrimSpace(s))
    return err == nil && (u.Scheme == "http" || u.Scheme == "https")
}

Prevention

When it happens

Trigger: url.Parse(address) returns a non-nil error — typically a stray space or control character in the URL, a missing scheme combined with other invalid syntax, or a value that is not a URL at all.

Common situations: Variable interpolation leaves a leading space; address was built by string concatenation that introduced a newline; user pasted a path without scheme; trailing slash issues are not this error (those parse fine).

Understand the failure class

Related errors


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

Appendix: source

Thrown at internal/backend/remote-state/http/backend.go:133

	backendbase.Base

	client *httpClient
}

func (b *Backend) Configure(configVal cty.Value) tfdiags.Diagnostics {
	address := backendbase.GetAttrEnvDefaultFallback(
		configVal, "address",
		"TF_HTTP_ADDRESS", cty.StringVal(""),
	).AsString()
	if address == "" {
		return backendbase.ErrorAsDiagnostics(
			fmt.Errorf("address argument is required"),
		)
	}
	updateURL, err := url.Parse(address)
	if err != nil {
		return backendbase.ErrorAsDiagnostics(
			fmt.Errorf("failed to parse address URL: %s", err),
		)
	}
	if updateURL.Scheme != "http" && updateURL.Scheme != "https" {
		return backendbase.ErrorAsDiagnostics(
			fmt.Errorf("address must be HTTP or HTTPS"),
		)
	}

	updateMethod := backendbase.GetAttrEnvDefaultFallback(
		configVal, "update_method",
		"TF_HTTP_UPDATE_METHOD", cty.StringVal("POST"),
	).AsString()

	var lockURL *url.URL
	if v := backendbase.GetAttrEnvDefault(configVal, "lock_address", "TF_HTTP_LOCK_ADDRESS"); !v.IsNull() {
		var err error
		lockURL, err = url.Parse(v.AsString())
		if err != nil {

View on GitHub (pinned to d32a084675)