{"record":{"id":"556a5c3f26dd9950","repo":"hashicorp/terraform","slug":"unlock-address-must-be-http-or-https","errorCode":null,"errorMessage":"unlock_address must be HTTP or HTTPS","messagePattern":"unlock_address must be HTTP or HTTPS","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/backend/remote-state/http/backend.go","lineNumber":178,"sourceCode":"\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\" {\n\t\t\treturn backendbase.ErrorAsDiagnostics(\n\t\t\t\tfmt.Errorf(\"unlock_address must be HTTP or HTTPS\"),\n\t\t\t)\n\t\t}\n\t}\n\tunlockMethod := backendbase.GetAttrEnvDefaultFallback(\n\t\tconfigVal, \"unlock_method\",\n\t\t\"TF_HTTP_UNLOCK_METHOD\", cty.StringVal(\"UNLOCK\"),\n\t).AsString()\n\n\tretryMax, err := backendbase.IntValue(\n\t\tbackendbase.GetAttrEnvDefaultFallback(\n\t\t\tconfigVal, \"retry_max\",\n\t\t\t\"TF_HTTP_RETRY_MAX\", cty.NumberIntVal(2),\n\t\t),\n\t)\n\tif err != nil {\n\t\treturn backendbase.ErrorAsDiagnostics(\n\t\t\tfmt.Errorf(\"invalid retry_max: %s\", err),\n\t\t)","sourceCodeStart":160,"sourceCodeEnd":196,"githubUrl":"https://github.com/hashicorp/terraform/blob/c9def3e214014c1188faabfc4a5bde5095139765/internal/backend/remote-state/http/backend.go#L160-L196","documentation":"Raised in Configure after unlock_address parses successfully but its scheme is neither http nor https. The backend only speaks HTTP/HTTPS for state I/O, so file://, ftp://, or a schemeless host are rejected outright. Distinct from error 240 which fires when parsing itself fails.","triggerScenarios":"unlock_address set to a non-HTTP scheme such as \"file:///tmp/unlock\", \"ftp://host/unlock\", or a bare \"state.corp/unlock\" that url.Parse interprets as scheme=\"state.corp\". Triggered during backend Configure at `terraform init`.","commonSituations":"Typo dropping the scheme prefix; copy-paste from an internal doc that lists just the host/path; accidentally prefixing with the workspace name instead of http://.","solutions":["Prefix unlock_address with http:// or https:// (https:// strongly preferred).","If you intended a plain hostname, rewrite as \"https://state.corp/unlock\".","Double-check the TF_HTTP_UNLOCK_ADDRESS env var is not inherited from a different tool expecting a different scheme."],"exampleFix":"// before\nunlock_address = \"state.corp/unlock\"\n// after\nunlock_address = \"https://state.corp/unlock\"","handlingStrategy":"validation","validationCode":"import \"net/url\"\nfunc assertHTTPScheme(raw string) error {\n  u, err := url.Parse(raw)\n  if err != nil { return err }\n  if u.Scheme != \"http\" && u.Scheme != \"https\" {\n    return fmt.Errorf(\"scheme must be http or https, got %q\", u.Scheme)\n  }\n  return nil\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Standardize all state endpoints on https://.","Reject config submissions whose URLs lack a scheme in code review.","Generate URLs from a single typed config struct rather than free-form strings."],"tags":["config","url-validation","http-backend","terraform"],"analyzedSha":"c9def3e214014c1188faabfc4a5bde5095139765","analyzedAt":"2026-08-07T15:39:49.278Z","schemaVersion":2},"datasetVersion":"2026-08-07T21:17:07.882Z"}