cloudflare/cloudflared · error

An api-url was not provided for the Cloudflare API client

Error message

An api-url was not provided for the Cloudflare API client

What it means

credentials.User.Client builds a Cloudflare API client (cloudflare-go cfapi) from the user's tunnel credentials. Because the API endpoint determines where certificate/zone/account calls go, an empty apiURL is rejected up front with this error before any client is constructed.

Source

Thrown at credentials/credentials.go:49

	return c.cert.ZoneID
}

func (c User) APIToken() string {
	return c.cert.APIToken
}

func (c User) CertPath() string {
	return c.certPath
}

func (c User) IsFEDEndpoint() bool {
	return c.cert.Endpoint == FedEndpoint
}

// Client uses the user credentials to create a Cloudflare API client
func (c *User) Client(apiURL string, userAgent string, log *zerolog.Logger) (cfapi.Client, error) {
	if apiURL == "" {
		return nil, errors.New("An api-url was not provided for the Cloudflare API client")
	}
	client, err := cfapi.NewRESTClient(
		apiURL,
		c.cert.AccountID,
		c.cert.ZoneID,
		c.cert.APIToken,
		userAgent,
		log,
	)
	if err != nil {
		return nil, err
	}
	return client, nil
}

// Read will load and read the origin cert.pem to load the user credentials
func Read(originCertPath string, log *zerolog.Logger) (*User, error) {
	originCertLog := log.With().

View on GitHub (pinned to 2253eeeb25)

Solutions

  1. Pass an explicit apiURL, e.g. https://api.cloudflare.com/client/v4, to User.Client
  2. Check that the --api-url flag or its config-file equivalent is actually set before creating the client
  3. Default the value in your code: if apiURL == "" use the standard Cloudflare API base URL

Example fix

// before
apiClient, err := user.Client("", userAgent, log)
// after
if apiURL == "" {
    apiURL = "https://api.cloudflare.com/client/v4"
}
apiClient, err := user.Client(apiURL, userAgent, log)
Defensive patterns

Strategy: validation

Validate before calling

if apiURL == "" {
    return errors.New("api-url must be set (e.g. https://api.cloudflare.com/client/v4) before creating the credentials client")
}

Type guard

func apiURLProvided(apiURL string) bool {
    u, err := url.Parse(apiURL)
    return err == nil && u.Scheme != "" && u.Host != ""
}

Try / catch

client, err := user.Client(apiURL, userAgent, log)
if err != nil && strings.Contains(err.Error(), "api-url was not provided") {
    apiURL = "https://api.cloudflare.com/client/v4"
    client, err = user.Client(apiURL, userAgent, log)
}

Prevention

When it happens

Trigger: Calling User.Client with apiURL == "" — e.g. the api-url value from flags/config was never set or resolved before constructing the client (as exercised by TestCredentialsClient).

Common situations: Custom setups that forgot to pass --api-url; code paths assuming the default Cloudflare API endpoint without supplying it; credentials loaded but the API URL config field left blank.

Understand the failure class

Background: "X is required", "must be set", "cannot be empty": the missing-required-config error family, from Vertex AI project/location to WeChat keys — this error's family across 18 libraries.

Related errors


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