crowdsecurity/crowdsec · info
ip not found
Error message
ip not found
What it means
ErrNotFound is returned when the CTI API responds HTTP 404 for the requested IP. GetIPInfo catches it and converts it into a benign empty &SmokeItem{}, so callers usually never see it; it exists to distinguish 'unknown IP' from real errors.
Source
Thrown at pkg/cticlient/client.go:25
"fmt"
"io"
"net/http"
"strings"
"github.com/crowdsecurity/crowdsec/pkg/apiclient/useragent"
log "github.com/sirupsen/logrus"
)
const (
CTIBaseUrl = "https://cti.api.crowdsec.net/v2"
smokeEndpoint = "/smoke"
fireEndpoint = "/fire"
)
var (
ErrUnauthorized = errors.New("unauthorized")
ErrLimit = errors.New("request quota exceeded, please reduce your request rate")
ErrNotFound = errors.New("ip not found")
ErrDisabled = errors.New("cti is disabled")
ErrUnknown = errors.New("unknown error")
defaultUserAgent = useragent.Default()
)
type CrowdsecCTIClient struct {
httpClient *http.Client
apiKey string
Logger *log.Entry
UserAgent string
}
func (c *CrowdsecCTIClient) doRequest(ctx context.Context, method string, endpoint string, params map[string]string) ([]byte, error) {
url := CTIBaseUrl + endpoint
if len(params) > 0 {
url += "?"
for k, v := range params {
url += fmt.Sprintf("%s=%s&", k, v)View on GitHub (pinned to 909b515798)
Solutions
- No fix needed: GetIPInfo already returns an empty SmokeItem for this case
- If calling doRequest directly, handle errors.Is(err, ErrNotFound) as an empty result rather than a failure
- Validate/skip private and reserved IPs before calling CTI
Example fix
// before
if err != nil { return err }
// after
if errors.Is(err, cticlient.ErrNotFound) {
return &cticlient.SmokeItem{}, nil
} Defensive patterns
Strategy: fallback
Validate before calling
// skip private/reserved IPs before querying CTI
if ip := net.ParseIP(s); ip == nil || ip.IsPrivate() || ip.IsLoopback() { return nil } Type guard
func isPublicIP(s string) bool { ip := net.ParseIP(s); return ip != nil && !ip.IsPrivate() && !ip.IsLoopback() } Try / catch
resp, err := ctiClient.GetIPInfo(ip)
if errors.Is(err, cticlient.ErrNotFound) {
resp = &cticlient.SmokeItem{} // empty result, not an error
} Prevention
- Treat 404 as 'no data', never as a failure that breaks enrichment
- Pre-filter private, loopback and link-local addresses
- Assume any public IP may legitimately be absent from the CTI DB
When it happens
Trigger: GetIPInfo called with an IP the CTI database has no record of (smokeEndpoint/<ip> returns 404).
Common situations: Looking up private/reserved addresses, fresh IPs never observed by CrowdSec, or IPv6 ranges outside CTI coverage.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- unauthorized
- request quota exceeded, please reduce your request rate
- failed to decode response: %w
- unable to query PAPI : %s (%d)
- unexpected http code : %s
AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06).
Data as JSON: /api/errors/4d217bcbc606c365.
Report an issue: GitHub.