{"record":{"id":"79fa4edce71ec0d3","repo":"hashicorp/terraform","slug":"failed-to-make-s-http-request-s","errorCode":null,"errorMessage":"Failed to make %s HTTP request: %s","messagePattern":"Failed to make (.+?) HTTP request: (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/backend/remote-state/http/client.go","lineNumber":53,"sourceCode":"\tClient   *retryablehttp.Client\n\tUsername string\n\tPassword string\n\n\tlockID       string\n\tjsonLockInfo []byte\n}\n\nfunc (c *httpClient) httpRequest(method string, url *url.URL, data *[]byte, what string) (*http.Response, error) {\n\t// If we have data we need a reader\n\tvar reader io.Reader = nil\n\tif data != nil {\n\t\treader = bytes.NewReader(*data)\n\t}\n\n\t// Create the request\n\treq, err := retryablehttp.NewRequest(method, url.String(), reader)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"Failed to make %s HTTP request: %s\", what, err)\n\t}\n\t// Set up basic auth\n\tif c.Username != \"\" {\n\t\treq.SetBasicAuth(c.Username, c.Password)\n\t}\n\n\t// Work with data/body\n\tif data != nil {\n\t\treq.Header.Set(\"Content-Type\", \"application/json\")\n\t\treq.ContentLength = int64(len(*data))\n\n\t\t// Generate the MD5\n\t\thash := md5.Sum(*data)\n\t\tb64 := base64.StdEncoding.EncodeToString(hash[:])\n\t\treq.Header.Set(\"Content-MD5\", b64)\n\t}\n\n\t// Make the request","sourceCodeStart":35,"sourceCodeEnd":71,"githubUrl":"https://github.com/hashicorp/terraform/blob/c9def3e214014c1188faabfc4a5bde5095139765/internal/backend/remote-state/http/client.go#L35-L71","documentation":"Inside httpClient.httpRequest, retryablehttp.NewRequest() returned an error before any network call. retryablehttp wraps net/http.NewRequest, so this indicates malformed method, an invalid URL string, or an unreadable body reader — a request-construction problem, not a transport one. The '%s' is the human label of the operation (get state / upload state / lock / unlock / delete state).","triggerScenarios":"A URL whose .String() produces something http.NewRequest rejects (control characters in host/path), an empty or non-token HTTP method in lock_method/unlock_method/update_method, or a nil body reader passed where one is required. Fires on the first state operation (Get/Put/Delete/Lock/Unlock) after Configure.","commonSituations":"Custom update_method set to an invalid token like \"POST \" with trailing space; lock_method misconfigured to lowercase \"lock\"; URL constructed with embedded NUL bytes from a bad template substitution.","solutions":["Validate lock_method, unlock_method, and update_method are uppercase valid HTTP method tokens (GET/POST/PUT/LOCK/UNLOCK/etc.).","Confirm the address/lock_address/unlock_address values do not contain stray control characters or whitespace after URL encoding.","If reproducing in a wrapper, construct the same retryablehttp.NewRequest in a unit test to surface the precise error."],"exampleFix":"// before\nupdate_method = \"PUT \"\n// after\nupdate_method = \"PUT\"","handlingStrategy":"validation","validationCode":"import (\n  \"github.com/hashicorp/go-retryablehttp\"\n)\nfunc validateHTTPRequest(method string, u string) error {\n  _, err := retryablehttp.NewRequest(method, u, nil)\n  return err\n}","typeGuard":"func isValidMethod(m string) bool {\n  if m == \"\" { return false }\n  for _, r := range m {\n    if r < 'A' || r > 'Z' { return false }\n  }\n  return true\n}","tryCatchPattern":null,"preventionTips":["Use only uppercase RFC 7230 method tokens for *_method attributes.","URL-encode dynamic address components.","Smoke-test method/URL construction in a unit test mirroring httpRequest."],"tags":["http","request-construction","http-backend","terraform"],"analyzedSha":"c9def3e214014c1188faabfc4a5bde5095139765","analyzedAt":"2026-08-07T15:39:49.278Z","schemaVersion":2},"datasetVersion":"2026-08-07T20:17:04.800Z"}