{"record":{"id":"320f2ea1d17b24f4","repo":"cloudflare/cloudflared","slug":"can-t-create-s-request","errorCode":null,"errorMessage":"can't create %s request","messagePattern":"can't create (.+?) request","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cfapi/base_client.go","lineNumber":99,"sourceCode":"\t\t\tTimeout:   defaultTimeout,\n\t\t},\n\t\tlog: log,\n\t}, nil\n}\n\nfunc (r *RESTClient) sendRequest(method string, url url.URL, body interface{}) (*http.Response, error) {\n\tvar bodyReader io.Reader\n\tif body != nil {\n\t\tif bodyBytes, err := json.Marshal(body); err != nil {\n\t\t\treturn nil, errors.Wrap(err, \"failed to serialize json body\")\n\t\t} else {\n\t\t\tbodyReader = bytes.NewBuffer(bodyBytes)\n\t\t}\n\t}\n\n\treq, err := http.NewRequest(method, url.String(), bodyReader)\n\tif err != nil {\n\t\treturn nil, errors.Wrapf(err, \"can't create %s request\", method)\n\t}\n\treq.Header.Set(\"User-Agent\", r.userAgent)\n\tif bodyReader != nil {\n\t\treq.Header.Set(\"Content-Type\", jsonContentType)\n\t}\n\treq.Header.Add(\"Authorization\", fmt.Sprintf(\"Bearer %s\", r.authToken))\n\treq.Header.Add(\"Accept\", \"application/json;version=1\")\n\treturn r.client.Do(req)\n}\n\nfunc parseResponseEnvelope(reader io.Reader) (*response, error) {\n\t// Schema for Tunnelstore responses in the v1 API.\n\t// Roughly, it's a wrapper around a particular result that adds failures/errors/etc\n\tvar result response\n\t// First, parse the wrapper and check the API call succeeded\n\tif err := json.NewDecoder(reader).Decode(&result); err != nil {\n\t\treturn nil, errors.Wrap(err, \"failed to decode response\")\n\t}","sourceCodeStart":81,"sourceCodeEnd":117,"githubUrl":"https://github.com/cloudflare/cloudflared/blob/2253eeeb25a44a713a4b60b8ba1e1b3f377d1a0f/cfapi/base_client.go#L81-L117","documentation":"RESTClient.sendRequest wraps http.NewRequest failures with 'can't create %s request' (method name interpolated). http.NewRequest fails when the URL string is unparseable or the body reader is invalid, so this means the request could not be constructed before any network call was made.","triggerScenarios":"Calling any RESTClient method when the client's endpoint URL is invalid (e.g. NewRESTClient got a baseURL that parseable initially but produces an unparseable final URL), or passing a bad io.Reader body.","commonSituations":"Custom/proxied API base URL misconfiguration; URL built with unescaped characters; misconfigured client instance shared across the app.","solutions":["Check the client's baseURL/accountTag/zoneTag for characters that break URL parsing.","Log the target url.String() before the call to spot malformed URLs.","Recreate the client with the default API base URL to isolate the issue.","Ensure the body passed is a valid io.Reader (bytes.Buffer, strings.Reader)."],"exampleFix":"// before\nclient, _ := cfapi.NewRESTClient(\"ht tp://proxy\", ...)\n// after\nclient, _ := cfapi.NewRESTClient(\"http://proxy\", ...)","handlingStrategy":"validation","validationCode":"u, err := url.Parse(baseURL)\nif err != nil || u.Scheme == \"\" || u.Host == \"\" {\n\treturn fmt.Errorf(\"invalid API base URL: %q\", baseURL)\n}","typeGuard":null,"tryCatchPattern":"resp, err := client.GetRouteByIP(t, ip)\nif err != nil {\n\tif strings.Contains(err.Error(), \"can't create\") {\n\t\treturn fmt.Errorf(\"malformed cfapi client URL: %w\", err)\n\t}\n\treturn err\n}","preventionTips":["Validate baseURL with url.Parse before NewRESTClient.","Log the request URL when wrapping client errors.","Rebuild the client with defaults to isolate configuration problems."],"tags":["go","http","api-client","url"],"backgroundTag":"http-request-failed","analyzedSha":"2253eeeb25a44a713a4b60b8ba1e1b3f377d1a0f","analyzedAt":"2026-09-06T04:14:33.757Z","contentChangedAt":"2026-09-06T04:14:33.757Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}