cloudflare/cloudflared · error

failed to create virtual network account-level endpoint

Error message

failed to create virtual network account-level endpoint

What it means

NewRESTClient builds the account-level virtual networks endpoint (baseURL + /accounts/<accountTag>/teamnet/virtual_networks) and wraps any url.Parse failure with this message. It indicates the composed URL string was not a valid URL.

Source

Thrown at cfapi/base_client.go:59

	accountRoutes url.URL
	accountVnets  url.URL
}

var _ Client = (*RESTClient)(nil)

func NewRESTClient(baseURL, accountTag, zoneTag, authToken, userAgent string, log *zerolog.Logger) (*RESTClient, error) {
	baseURL = strings.TrimSuffix(baseURL, "/")
	accountLevelEndpoint, err := url.Parse(fmt.Sprintf("%s/accounts/%s/cfd_tunnel", baseURL, accountTag))
	if err != nil {
		return nil, errors.Wrap(err, "failed to create account level endpoint")
	}
	accountRoutesEndpoint, err := url.Parse(fmt.Sprintf("%s/accounts/%s/teamnet/routes", baseURL, accountTag))
	if err != nil {
		return nil, errors.Wrap(err, "failed to create route account-level endpoint")
	}
	accountVnetsEndpoint, err := url.Parse(fmt.Sprintf("%s/accounts/%s/teamnet/virtual_networks", baseURL, accountTag))
	if err != nil {
		return nil, errors.Wrap(err, "failed to create virtual network account-level endpoint")
	}
	zoneLevelEndpoint, err := url.Parse(fmt.Sprintf("%s/zones/%s/tunnels", baseURL, zoneTag))
	if err != nil {
		return nil, errors.Wrap(err, "failed to create account level endpoint")
	}
	httpTransport := http.Transport{
		TLSHandshakeTimeout:   defaultTimeout,
		ResponseHeaderTimeout: defaultTimeout,
	}
	_ = http2.ConfigureTransport(&httpTransport)
	return &RESTClient{
		baseEndpoints: &baseEndpoints{
			accountLevel:  *accountLevelEndpoint,
			zoneLevel:     *zoneLevelEndpoint,
			accountRoutes: *accountRoutesEndpoint,
			accountVnets:  *accountVnetsEndpoint,
		},
		authToken: authToken,

View on GitHub (pinned to 2253eeeb25)

Solutions

  1. Check baseURL and accountTag for stray characters and trim/fix them.
  2. Use the default API base URL unless a custom endpoint is required.
  3. Validate/escape the account tag before client construction.

Example fix

// before
baseURL := "https://api.cloudflare.com/\n"
// after
baseURL := strings.TrimSpace("https://api.cloudflare.com")
Defensive patterns

Strategy: validation

Validate before calling

u, err := url.Parse(fmt.Sprintf("%s/accounts/%s/teamnet/virtual_networks", baseURL, accountTag))
if err != nil {
	return fmt.Errorf("invalid virtual networks endpoint URL: %w", err)
}

Try / catch

client, err := cfapi.NewRESTClient(baseURL, accountTag, zoneTag, token, ua, log)
if err != nil {
	return fmt.Errorf("cfapi init: %w", err)
}

Prevention

When it happens

Trigger: baseURL or accountTag containing spaces, control characters, or malformed percent-escapes making the virtual networks endpoint URL unparseable.

Common situations: Custom API endpoint configuration errors; account tag copied with surrounding whitespace or quotes from a config file.

Understand the failure class

Background: "Invalid URL" errors: why new URL(), URI.parse, and reqwest::Url reject your string — missing scheme, whitespace, and bad path format — this error's family across 39 libraries.

Related errors


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