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
- Read the wrapped inner error (and the 'CTI API error' warning log) for the concrete cause.
- Check network connectivity from the CrowdSec host to the CTI endpoint (curl the API).
- Verify the CTI API key is valid; re-register or update the key if 401/403.
- 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
- Ensure outbound HTTPS to the CTI API works from the host
- Validate the API key with a manual curl before deployment
- Handle ErrDisabled/ErrLimit/ErrNotFound explicitly instead of falling to default
- Cache results to reduce API dependency
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
- unauthorized
- request quota exceeded, please reduce your request rate
- ip not found
- unexpected http code : %s
- unable to convert '%s' to int: %w: %w
AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06).
Data as JSON: /api/errors/577af13d1b5b8c6d.
Report an issue: GitHub.