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
- Set lock_address to an http:// or https:// URL.
- Mirror the scheme of the main 'address' — typically 'https://.../lock' alongside 'https://...'.
- 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
- Keep lock_address scheme identical to address (both https in production).
- Omit lock_address entirely if you do not need HTTP-level locking.
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
- address must be HTTP or HTTPS
- failed to parse lock_address URL
- unlock_address must be HTTP or HTTPS
- failed to parse unlock_address URL
- Unexpected HTTP response code
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)