crowdsecurity/crowdsec · error

APIKey is empty

Error message

APIKey is empty

What it means

APIKeyTransport is an http.RoundTripper that injects an API key into outgoing requests. RoundTrip refuses to execute if the transport's APIKey field is empty, because a request sent without a key would fail authentication downstream anyway.

Source

Thrown at pkg/apiclient/auth_key.go:22

	"errors"
	"net/http"
	"net/http/httputil"

	log "github.com/sirupsen/logrus"
)

type APIKeyTransport struct {
	APIKey string
	// Transport is the underlying HTTP transport to use when making requests.
	// It will default to http.DefaultTransport if nil.
	Transport     http.RoundTripper
	UserAgent     string
}

// RoundTrip implements the RoundTripper interface.
func (t *APIKeyTransport) RoundTrip(req *http.Request) (*http.Response, error) {
	if t.APIKey == "" {
		return nil, errors.New("APIKey is empty")
	}

	// We must make a copy of the Request so
	// that we don't modify the Request we were given. This is required by the
	// specification of http.RoundTripper.
	req = cloneRequest(req)
	req.Header.Add("X-Api-Key", t.APIKey)

	if t.UserAgent != "" {
		req.Header.Add("User-Agent", t.UserAgent)
	}

	log.Debugf("req-api: %s %s", req.Method, req.URL.String())

	if log.IsLevelEnabled(log.TraceLevel) {
		dump, _ := httputil.DumpRequest(req, true)
		log.Tracef("auth-api request: %s", string(dump))
	}

View on GitHub (pinned to 909b515798)

Solutions

  1. Set the APIKey field on the APIKeyTransport before using the client
  2. Load the key from config/env (e.g. LocalAPIider credentials) and validate it is non-empty at startup
  3. Regenerate credentials with cscli (e.g. 'cscli bouncers add') and put the key in the client config

Example fix

// before
tr := &apiclient.APIKeyTransport{Transport: base}
client := &http.Client{Transport: tr}
// after
if apiKey == "" {
    return nil, fmt.Errorf("missing API key")
}
tr := &apiclient.APIKeyTransport{APIKey: apiKey, Transport: base}
client := &http.Client{Transport: tr}
Defensive patterns

Strategy: validation

Validate before calling

// Go: check the key before constructing the transport
if apiKey == "" {
    return nil, fmt.Errorf("no API key configured for LAPI client")
}
tr := &apiclient.APIKeyTransport{APIKey: apiKey, Transport: http.DefaultTransport}

Try / catch

resp, err := client.Do(req)
if err != nil && strings.Contains(err.Error(), "APIKey is empty") {
    return fmt.Errorf("client misconfigured: %w", err)
}

Prevention

When it happens

Trigger: Constructing an APIKeyTransport (or an apiclient built on one) with an empty APIKey string and then issuing any HTTP request through it.

Common situations: Config file missing api_key / LAPI key; environment variable not set when building the client; reading the key from a file that is empty or failed to load; registering a bouncer without supplying its key.

Understand the failure class

Background: "API key is required" / "API key not found" / "No API key was set": the missing-api-key error family across 16 libraries — this error's family across 16 libraries.

Related errors


AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06). Data as JSON: /api/errors/ca4329f39a68ec84. Report an issue: GitHub.