cloudflare/cloudflared · error

can't create %s request

Error message

can't create %s request

What it means

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.

Source

Thrown at cfapi/base_client.go:99

			Timeout:   defaultTimeout,
		},
		log: log,
	}, nil
}

func (r *RESTClient) sendRequest(method string, url url.URL, body interface{}) (*http.Response, error) {
	var bodyReader io.Reader
	if body != nil {
		if bodyBytes, err := json.Marshal(body); err != nil {
			return nil, errors.Wrap(err, "failed to serialize json body")
		} else {
			bodyReader = bytes.NewBuffer(bodyBytes)
		}
	}

	req, err := http.NewRequest(method, url.String(), bodyReader)
	if err != nil {
		return nil, errors.Wrapf(err, "can't create %s request", method)
	}
	req.Header.Set("User-Agent", r.userAgent)
	if bodyReader != nil {
		req.Header.Set("Content-Type", jsonContentType)
	}
	req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", r.authToken))
	req.Header.Add("Accept", "application/json;version=1")
	return r.client.Do(req)
}

func parseResponseEnvelope(reader io.Reader) (*response, error) {
	// Schema for Tunnelstore responses in the v1 API.
	// Roughly, it's a wrapper around a particular result that adds failures/errors/etc
	var result response
	// First, parse the wrapper and check the API call succeeded
	if err := json.NewDecoder(reader).Decode(&result); err != nil {
		return nil, errors.Wrap(err, "failed to decode response")
	}

View on GitHub (pinned to 2253eeeb25)

Solutions

  1. Check the client's baseURL/accountTag/zoneTag for characters that break URL parsing.
  2. Log the target url.String() before the call to spot malformed URLs.
  3. Recreate the client with the default API base URL to isolate the issue.
  4. Ensure the body passed is a valid io.Reader (bytes.Buffer, strings.Reader).

Example fix

// before
client, _ := cfapi.NewRESTClient("ht tp://proxy", ...)
// after
client, _ := cfapi.NewRESTClient("http://proxy", ...)
Defensive patterns

Strategy: validation

Validate before calling

u, err := url.Parse(baseURL)
if err != nil || u.Scheme == "" || u.Host == "" {
	return fmt.Errorf("invalid API base URL: %q", baseURL)
}

Try / catch

resp, err := client.GetRouteByIP(t, ip)
if err != nil {
	if strings.Contains(err.Error(), "can't create") {
		return fmt.Errorf("malformed cfapi client URL: %w", err)
	}
	return err
}

Prevention

When it happens

Trigger: 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.

Common situations: Custom/proxied API base URL misconfiguration; URL built with unescaped characters; misconfigured client instance shared across the app.

Understand the failure class

Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.

Related errors


AI-assisted analysis of cloudflare/cloudflared@2253eeeb25 (2026-09-06). Data as JSON: /api/errors/320f2ea1d17b24f4. Report an issue: GitHub.