{"record":{"id":"e7affb113dc21c77","repo":"opentofu/opentofu","slug":"failed-to-parse-address-url-w","errorCode":null,"errorMessage":"failed to parse address URL: %w","messagePattern":"failed to parse address URL: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/backend/remote-state/http/backend.go","lineNumber":215,"sourceCode":"\tif clientCertificatePem != \"\" && clientPrivateKeyPem != \"\" {\n\t\t// attach a client certificate to the TLS handshake (aka mTLS)\n\t\tcertificate, err := tls.X509KeyPair([]byte(clientCertificatePem), []byte(clientPrivateKeyPem))\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"cannot load client certificate: %w\", err)\n\t\t}\n\t\ttlsConfig.Certificates = []tls.Certificate{certificate}\n\t}\n\n\treturn nil\n}\n\nfunc (b *Backend) configure(ctx context.Context) error {\n\tdata := schema.FromContextBackendConfig(ctx)\n\n\taddress := data.Get(\"address\").(string)\n\tupdateURL, err := url.Parse(address)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to parse address URL: %w\", err)\n\t}\n\tif updateURL.Scheme != \"http\" && updateURL.Scheme != \"https\" {\n\t\treturn fmt.Errorf(\"address must be HTTP or HTTPS\")\n\t}\n\n\tupdateMethod := data.Get(\"update_method\").(string)\n\n\tvar lockURL *url.URL\n\tif v, ok := data.GetOk(\"lock_address\"); ok && v.(string) != \"\" {\n\t\tvar err error\n\t\tlockURL, err = url.Parse(v.(string))\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"failed to parse lockAddress URL: %w\", err)\n\t\t}\n\t\tif lockURL.Scheme != \"http\" && lockURL.Scheme != \"https\" {\n\t\t\treturn fmt.Errorf(\"lockAddress must be HTTP or HTTPS\")\n\t\t}\n\t}","sourceCodeStart":197,"sourceCodeEnd":233,"githubUrl":"https://github.com/opentofu/opentofu/blob/3561785c48c1ce615e7c50261bd351f26053efa2/internal/backend/remote-state/http/backend.go#L197-L233","documentation":"During configure(), the 'address' attribute is parsed with url.Parse and any error is wrapped as 'failed to parse address URL'. url.Parse rarely fails, but it does for structurally malformed URLs such as an unclosed IPv6 bracket or embedded control characters, so this fires before the http/https scheme check.","triggerScenarios":"address = \"https://[::1\" (missing ']'), an address containing a control character or newline (often from a templated variable), or garbage produced by concatenating empty config pieces.","commonSituations":"Assembling the URL from multiple -backend-config flags or CI variables where one piece is empty or mangled; IPv6 literals typed by hand; secrets managers or env files returning values with trailing newlines.","solutions":["Print the fully rendered address and test it with curl to confirm it parses","Fix the malformed component (close brackets, remove spaces, control characters, newlines)","Set the complete URL as a single literal in the backend block instead of concatenating variables"],"exampleFix":"# before\naddress = \"https://[::1\"\n# after\naddress = \"https://[::1]/state\"","handlingStrategy":"validation","validationCode":"// Validate the rendered address before tofu init\nu, err := url.Parse(rawAddress)\nif err != nil {\n    log.Fatalf(\"address does not parse: %v\", err)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Render the final address in CI logs and curl it before init","Trim whitespace and newlines from variables that feed the address","Prefer one full literal URL over concatenating parts"],"tags":["http","backend","url","configuration","init"],"backgroundTag":null,"analyzedSha":"3561785c48c1ce615e7c50261bd351f26053efa2","analyzedAt":"2026-08-15T23:27:16.226Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}