{"record":{"id":"3819763c7e06247d","repo":"hashicorp/terraform","slug":"lock-address-must-be-http-or-https","errorCode":null,"errorMessage":"lock_address must be HTTP or HTTPS","messagePattern":"lock_address must be HTTP or HTTPS","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/backend/remote-state/http/backend.go","lineNumber":158,"sourceCode":"\t}\n\n\tupdateMethod := backendbase.GetAttrEnvDefaultFallback(\n\t\tconfigVal, \"update_method\",\n\t\t\"TF_HTTP_UPDATE_METHOD\", cty.StringVal(\"POST\"),\n\t).AsString()\n\n\tvar lockURL *url.URL\n\tif v := backendbase.GetAttrEnvDefault(configVal, \"lock_address\", \"TF_HTTP_LOCK_ADDRESS\"); !v.IsNull() {\n\t\tvar err error\n\t\tlockURL, err = url.Parse(v.AsString())\n\t\tif err != nil {\n\t\t\treturn backendbase.ErrorAsDiagnostics(\n\t\t\t\tfmt.Errorf(\"failed to parse lock_address URL: %s\", err),\n\t\t\t)\n\t\t}\n\t\tif lockURL.Scheme != \"http\" && lockURL.Scheme != \"https\" {\n\t\t\treturn backendbase.ErrorAsDiagnostics(\n\t\t\t\tfmt.Errorf(\"lock_address must be HTTP or HTTPS\"),\n\t\t\t)\n\t\t}\n\t}\n\tlockMethod := backendbase.GetAttrEnvDefaultFallback(\n\t\tconfigVal, \"lock_method\",\n\t\t\"TF_HTTP_LOCK_METHOD\", cty.StringVal(\"LOCK\"),\n\t).AsString()\n\n\tvar unlockURL *url.URL\n\tif v := backendbase.GetAttrEnvDefault(configVal, \"unlock_address\", \"TF_HTTP_UNLOCK_ADDRESS\"); !v.IsNull() {\n\t\tvar err error\n\t\tunlockURL, err = url.Parse(v.AsString())\n\t\tif err != nil {\n\t\t\treturn backendbase.ErrorAsDiagnostics(\n\t\t\t\tfmt.Errorf(\"failed to parse unlock_address URL: %s\", err),\n\t\t\t)\n\t\t}\n\t\tif unlockURL.Scheme != \"http\" && unlockURL.Scheme != \"https\" {","sourceCodeStart":140,"sourceCodeEnd":176,"githubUrl":"https://github.com/hashicorp/terraform/blob/c9def3e214014c1188faabfc4a5bde5095139765/internal/backend/remote-state/http/backend.go#L140-L176","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Prefix lock_address with 'https://' (or 'http://' for local dev).","Remove lock_address entirely if your state API has no separate lock endpoint.","Confirm scheme matches address; the HTTP backend does not inherit it automatically."],"exampleFix":"// before\nlock_address = \"state.example.com/lock\"   // no scheme\n\n// after\nlock_address = \"https://state.example.com/lock\"","handlingStrategy":"validation","validationCode":"if lockAddr != \"\" {\n    u, err := url.Parse(lockAddr)\n    if err != nil { log.Fatal(err) }\n    if u.Scheme != \"http\" && u.Scheme != \"https\" {\n        log.Fatalf(\"lock_address scheme must be http or https, got %q\", u.Scheme)\n    }\n}","typeGuard":"func isHTTPScheme(s string) bool {\n    u, err := url.Parse(s)\n    return err == nil && (u.Scheme == \"http\" || u.Scheme == \"https\")\n}","tryCatchPattern":null,"preventionTips":["Always prefix lock_address with https://.","Keep scheme consistent with address.","Omit lock_address entirely when not using a separate lock endpoint."],"tags":["http","backend","url","scheme","locking","config-validation"],"analyzedSha":"c9def3e214014c1188faabfc4a5bde5095139765","analyzedAt":"2026-08-07T15:39:49.278Z","schemaVersion":2},"datasetVersion":"2026-08-07T21:17:07.882Z"}