{"record":{"id":"c0355916a487adff","repo":"crowdsecurity/crowdsec","slug":"cti-is-disabled","errorCode":null,"errorMessage":"cti is disabled","messagePattern":"cti is disabled","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"pkg/cticlient/client.go","lineNumber":26,"sourceCode":"\t\"io\"\n\t\"net/http\"\n\t\"strings\"\n\n\t\"github.com/crowdsecurity/crowdsec/pkg/apiclient/useragent\"\n\tlog \"github.com/sirupsen/logrus\"\n)\n\nconst (\n\tCTIBaseUrl    = \"https://cti.api.crowdsec.net/v2\"\n\tsmokeEndpoint = \"/smoke\"\n\tfireEndpoint  = \"/fire\"\n)\n\nvar (\n\tErrUnauthorized  = errors.New(\"unauthorized\")\n\tErrLimit         = errors.New(\"request quota exceeded, please reduce your request rate\")\n\tErrNotFound      = errors.New(\"ip not found\")\n\tErrDisabled      = errors.New(\"cti is disabled\")\n\tErrUnknown       = errors.New(\"unknown error\")\n\tdefaultUserAgent = useragent.Default()\n)\n\ntype CrowdsecCTIClient struct {\n\thttpClient *http.Client\n\tapiKey     string\n\tLogger     *log.Entry\n\tUserAgent  string\n}\n\nfunc (c *CrowdsecCTIClient) doRequest(ctx context.Context, method string, endpoint string, params map[string]string) ([]byte, error) {\n\turl := CTIBaseUrl + endpoint\n\tif len(params) > 0 {\n\t\turl += \"?\"\n\t\tfor k, v := range params {\n\t\t\turl += fmt.Sprintf(\"%s=%s&\", k, v)\n\t\t}","sourceCodeStart":8,"sourceCodeEnd":44,"githubUrl":"https://github.com/crowdsecurity/crowdsec/blob/909b5157986a2b2c2163300fdaef5ed01289f7d2/pkg/cticlient/client.go#L8-L44","documentation":"ErrDisabled signals that CTI enrichment is disabled because no API key was configured (or the client is nil). InitCrowdsecCTI returns it when the key is absent/empty, and the CTI expr helpers return it for every lookup when CTIApiEnabled is false.","triggerScenarios":"ctiexpr registration with an empty/missing api_key config; IpCTI/CTI expr function called while CTIApiEnabled is false (nil client).","commonSituations":"Deployments without a CrowdSec CTI subscription where profiles/alerts still reference CTI expr functions; CTI_API_KEY env var not set on the LAPI.","solutions":["Set a valid CTI API key in the crowdsec configuration (api.cti.api_key) or CTI_API_KEY env to enable CTI","Remove CTI functions (IpCTI etc.) from profiles/alert workflows if you don't use CTI","Handle errors.Is(err, cticlient.ErrDisabled) gracefully and skip enrichment"],"exampleFix":"// config.yaml before (CTI referenced but no key)\n// after\napi:\n  cti:\n    enabled: true\n    key: <your-cti-api-key>","handlingStrategy":"type-guard","validationCode":"if cfg.CTI == nil || cfg.CTI.APIKey == \"\" { log.Warning(\"CTI disabled: no API key configured\") }","typeGuard":"func ctiEnabled(key *string) bool { return key != nil && *key != \"\" }","tryCatchPattern":"resp, err := cticlient.CrowdsecCTI(...)\nif errors.Is(err, cticlient.ErrDisabled) {\n    return &cticlient.SmokeItem{}, nil // skip enrichment silently\n}","preventionTips":["Set the CTI API key explicitly or remove CTI functions from profiles","Document that IpCTI requires an active CTI subscription","Gate CTI expr usage behind a config check at startup"],"tags":["config","cti","feature-flag","expr"],"backgroundTag":"missing-api-key","analyzedSha":"909b5157986a2b2c2163300fdaef5ed01289f7d2","analyzedAt":"2026-09-06T12:27:26.012Z","contentChangedAt":"2026-09-06T12:27:26.012Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}