hashicorp/terraform · error

lock_address must be HTTP or HTTPS

Error message

lock_address must be HTTP or HTTPS

What it means

lock_address parsed successfully but its scheme is neither 'http' nor 'https'. The backend applies the same scheme restriction to lock_address as it does to address, so an ftp/file/s3 scheme (or a URL that url.Parse accepts but with an unexpected scheme) is rejected.

Solutions

  1. Set lock_address to an http:// or https:// URL.
  2. Mirror the scheme of the main 'address' — typically 'https://.../lock' alongside 'https://...'.
  3. Remove lock_address entirely if you do not need HTTP-level locking (the backend then runs lockless).

Example fix

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

Strategy: validation

Validate before calling

# Pre-flight: assert lock_address scheme
if [ -n "$TF_HTTP_LOCK_ADDRESS" ]; then
  case "$TF_HTTP_LOCK_ADDRESS" in
    http://*|https://*) echo ok ;;
    *) echo "ERROR: lock_address must be http(s): $TF_HTTP_LOCK_ADDRESS"; exit 1 ;;
  esac
fi

Prevention

When it happens

Trigger: lock_address set with a non-HTTP scheme such as 'ftp://', 'file://', or a relative URL whose parsed scheme is empty yet bypassed the parse check (rare); most often a wrong-scheme copy-paste.

Common situations: lock_address copied from a different backend's URI; lock_address templated from a variable that accidentally prepended a non-http scheme.

Related errors


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

Appendix: 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 d32a084675)