hashicorp/terraform · error

lock_address must be HTTP or HTTPS

Error message

lock_address must be HTTP or HTTPS

What it means

After parsing lock_address, Configure() enforces scheme http or https, identical to the address-scheme check. A non-HTTP(S) scheme or empty scheme (URL without protocol prefix) is rejected because the lock call must be an HTTP request.

Source

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

	}

	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" {
			return backendbase.ErrorAsDiagnostics(
				fmt.Errorf("lock_address must be HTTP or HTTPS"),
			)
		}
	}
	lockMethod := backendbase.GetAttrEnvDefaultFallback(
		configVal, "lock_method",
		"TF_HTTP_LOCK_METHOD", cty.StringVal("LOCK"),
	).AsString()

	var unlockURL *url.URL
	if v := backendbase.GetAttrEnvDefault(configVal, "unlock_address", "TF_HTTP_UNLOCK_ADDRESS"); !v.IsNull() {
		var err error
		unlockURL, err = url.Parse(v.AsString())
		if err != nil {
			return backendbase.ErrorAsDiagnostics(
				fmt.Errorf("failed to parse unlock_address URL: %s", err),
			)
		}
		if unlockURL.Scheme != "http" && unlockURL.Scheme != "https" {

View on GitHub (pinned to c9def3e214)

Solutions

  1. Prefix lock_address with 'https://' (or 'http://' for local dev).
  2. Remove lock_address entirely if your state API has no separate lock endpoint.
  3. Confirm scheme matches address; the HTTP backend does not inherit it automatically.

Example fix

// before
lock_address = "state.example.com/lock"   // no scheme

// after
lock_address = "https://state.example.com/lock"
Defensive patterns

Strategy: validation

Validate before calling

if lockAddr != "" {
    u, err := url.Parse(lockAddr)
    if err != nil { log.Fatal(err) }
    if u.Scheme != "http" && u.Scheme != "https" {
        log.Fatalf("lock_address scheme must be http or https, got %q", u.Scheme)
    }
}

Type guard

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

Prevention

When it happens

Trigger: lock_address set to a value without an http(s):// scheme, or to ftp/file/etc. Triggered during 'terraform init' when lock_address is set.

Common situations: User set lock_address without a scheme assuming the backend would reuse address's scheme; copy-paste dropped the prefix; non-HTTP scheme by mistake.

Related errors


AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07). Data as JSON: /api/errors/3819763c7e06247d. Report an issue: GitHub.