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
- Pass an explicit apiURL, e.g. https://api.cloudflare.com/client/v4, to User.Client
- Check that the --api-url flag or its config-file equivalent is actually set before creating the client
- 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
- Default apiURL to https://api.cloudflare.com/client/v4 when unset
- Wire --api-url through flags/config consistently in your tooling
- Validate the API URL (scheme+host) at startup, before client construction
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
- failed to get checksums: {0}
- failed to upload checksum: {0}
- ErrUnauthorized
- ErrBadRequest
- ErrAPINoSuccess
AI-assisted analysis of cloudflare/cloudflared@2253eeeb25 (2026-09-06).
Data as JSON: /api/errors/95f7b4c55432129b.
Report an issue: GitHub.