crowdsecurity/crowdsec · error

unexpected error: %w

Error message

unexpected error: %w

What it means

CrowdsecCTI handles known CTI errors specially (ErrDisabled, ErrNotFound, ErrLimit/backoff). Any other error returned by the underlying CTI client (network failure, authentication problem, unexpected server response, bad JSON) falls into the default case and is wrapped as 'unexpected error: ...' alongside a Warnf log.

Source

Thrown at pkg/cticlient/ctiexpr/expr.go:132

	ctiClient.Logger.Infof("cti call for %s", ip)

	before := time.Now()

	ctiResp, err := ctiClient.GetIPInfo(ip)
	ctiClient.Logger.Debugf("request for %s took %v", ip, time.Since(before))
	if err != nil {
		switch {
		case errors.Is(err, cticlient.ErrUnauthorized):
			CTIApiEnabled = false
			ctiClient.Logger.Errorf("Invalid API key provided, disabling CTI API")
			return &cticlient.SmokeItem{}, cticlient.ErrUnauthorized
		case errors.Is(err, cticlient.ErrLimit):
			CTIBackOffUntil = time.Now().Add(CTIBackOffDuration)
			ctiClient.Logger.Errorf("CTI API is throttled, will try again in %s", CTIBackOffDuration)
			return &cticlient.SmokeItem{}, cticlient.ErrLimit
		default:
			ctiClient.Logger.Warnf("CTI API error : %s", err)
			return &cticlient.SmokeItem{}, fmt.Errorf("unexpected error: %w", err)
		}
	}

	if err := CTICache.SetWithExpire(ip, ctiResp, CacheExpiration); err != nil {
		ctiClient.Logger.Warningf("IpCTI : error while caching CTI : %s", err)
		return &cticlient.SmokeItem{}, cticlient.ErrUnknown
	}

	ctiClient.Logger.Tracef("CTI response : %v", *ctiResp)

	return ctiResp, nil
}

View on GitHub (pinned to 909b515798)

Solutions

  1. Read the wrapped inner error (and the 'CTI API error' warning log) for the concrete cause.
  2. Check network connectivity from the CrowdSec host to the CTI endpoint (curl the API).
  3. Verify the CTI API key is valid; re-register or update the key if 401/403.
  4. Retry after transient network/server issues; consider relying on cache to reduce calls.
Defensive patterns

Strategy: try-catch

Validate before calling

// check connectivity + key before bulk lookups
resp, err := http.Get(ctiEndpoint)
if err != nil || resp.StatusCode != 200 {
    return fmt.Errorf("CTI endpoint unreachable or auth invalid")
}

Try / catch

item, err := cti(ip)
switch {
case errors.Is(err, cticlient.ErrNotFound):
    // unknown IP, proceed
case errors.Is(err, cticlient.ErrLimit):
    // throttled, back off
case err != nil:
    log.Warnf("CTI lookup failed unexpectedly: %v", err)
}

Prevention

When it happens

Trigger: Calling the cti expr function when the underlying cticlient request fails with a non-categorized error: DNS/connectivity failure to the CTI endpoint, invalid API key (401) surfaced as a generic error, malformed API response, or TLS error.

Common situations: No outbound internet access from the CrowdSec host; wrong CTI API key in config; CTI API outage or changed response format; corporate proxy breaking HTTPS to the API.

Related errors


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