hashicorp/terraform · error

address must be HTTP or HTTPS

Error message

address must be HTTP or HTTPS

What it means

Thrown by Backend.Configure after url.Parse(address) succeeds but the URL scheme is neither 'http' nor 'https'. The HTTP backend only speaks HTTP(S); other schemes are rejected to prevent ambiguous behavior. The value comes from the 'address' attribute in the backend block or the TF_HTTP_ADDRESS environment variable.

Solutions

  1. Set address to a full absolute HTTP(S) URL, e.g. 'https://state.example.com/terraform/default'.
  2. If using TF_HTTP_ADDRESS, export it WITH the scheme: export TF_HTTP_ADDRESS=https://state.example.com/...
  3. Strip trailing whitespace/newlines from the value (e.g. tr -d '\r\n') when sourcing from a file or secret store.
  4. Confirm there is exactly one scheme token and no embedded spaces.

Example fix

// before
address = "state.example.com/terraform"
// or
address = "s3://mybucket/state"
// after
address = "https://state.example.com/terraform"
Defensive patterns

Strategy: validation

Validate before calling

# Pre-flight: ensure address is http(s) before terraform init
addr="${TF_HTTP_ADDRESS:-https://state.example.com/terraform}"
case "$addr" in
  http://*|https://*) echo "ok: $addr" ;;
  *) echo "ERROR: address must start with http:// or https:// — got: $addr"; exit 1 ;;
esac

Prevention

When it happens

Trigger: terraform init runs with the 'address' attribute (or TF_HTTP_ADDRESS) set to a URL whose scheme is not http/https — e.g. 'ftp://host', 'file:///path', 's3://bucket/key', or a bare host parsed with an unexpected scheme.

Common situations: Copy-pasting a storage URI from another backend (s3://, gcs://); omitting the https:// prefix so the host becomes a path; a typo like 'httpss://'; trailing whitespace or a newline appended by a secret manager.

Related errors


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

Appendix: source

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

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 {
			return backendbase.ErrorAsDiagnostics(
				fmt.Errorf("failed to parse lock_address URL: %s", err),
			)
		}
		if lockURL.Scheme != "http" && lockURL.Scheme != "https" {

View on GitHub (pinned to d32a084675)