{"record":{"id":"84f94aca2d6e8f93","repo":"crowdsecurity/crowdsec","slug":"object-not-found","errorCode":null,"errorMessage":"object not found","messagePattern":"object not found","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"pkg/database/errors.go","lineNumber":13,"sourceCode":"package database\n\nimport \"errors\"\n\nvar (\n\tUserExists        = errors.New(\"user already exist\")\n\tUserNotExists     = errors.New(\"user doesn't exist\")\n\tHashError         = errors.New(\"unable to hash\")\n\tInsertFail        = errors.New(\"unable to insert row\")\n\tQueryFail         = errors.New(\"unable to query\")\n\tUpdateFail        = errors.New(\"unable to update\")\n\tDeleteFail        = errors.New(\"unable to delete\")\n\tItemNotFound      = errors.New(\"object not found\")\n\tParseTimeFail     = errors.New(\"unable to parse time\")\n\tParseDurationFail = errors.New(\"unable to parse duration\")\n\tMarshalFail       = errors.New(\"unable to serialize\")\n\tBulkError         = errors.New(\"unable to insert bulk\")\n\tParseType         = errors.New(\"unable to parse type\")\n\tInvalidIPOrRange  = errors.New(\"invalid ip address / range\")\n\tInvalidFilter     = errors.New(\"invalid filter\")\n)\n","sourceCodeStart":1,"sourceCodeEnd":22,"githubUrl":"https://github.com/crowdsecurity/crowdsec/blob/909b5157986a2b2c2163300fdaef5ed01289f7d2/pkg/database/errors.go#L1-L22","documentation":"ItemNotFound is a sentinel error meaning the requested object does not exist in the database. It is returned when ent's IsNotFound(err) is true (e.g. GetAlertByID) and is mapped by the API layer (HandleDBErrors) to an HTTP 404 response.","triggerScenarios":"GetAlertByID with an alert ID not in the DB; ExpireDecisionByID with an unknown decision ID; any database call whose error passes through HandleDBErrors after ent.IsNotFound matched.","commonSituations":"Querying an alert that was already deleted or expired by retention, using a decision ID received from a stale bouncer cache, race between reading a list and fetching a specific ID.","solutions":["Verify the ID exists (cscli alerts list / cscli decisions list) before fetching.","Treat it as an expected 404: check errors.Is(err, database.ItemNotFound) and handle gracefully instead of retrying.","If IDs come from another component, refresh them (IDs are not stable across DB resets).","Check retention config — old alerts/decisions may have been purged."],"exampleFix":"// before\nalert, err := client.GetAlertByID(ctx, alertID)\nif err != nil { return err }\n// after\nalert, err := client.GetAlertByID(ctx, alertID)\nif errors.Is(err, database.ItemNotFound) {\n    log.Debugf(\"alert %d already gone\", alertID)\n    return nil\n} else if err != nil {\n    return err\n}","handlingStrategy":"try-catch","validationCode":"// Go: confirm existence first when ID source is external\n_, err := client.GetAlertByID(ctx, alertID)\nexists := !errors.Is(err, database.ItemNotFound)","typeGuard":"func isNotFound(err error) bool { return errors.Is(err, database.ItemNotFound) }","tryCatchPattern":"alert, err := client.GetAlertByID(ctx, alertID)\nswitch {\ncase errors.Is(err, database.ItemNotFound):\n    return nil // expected absence, not a failure\ncase err != nil:\n    return err\n}","preventionTips":["Always check errors.Is(err, database.ItemNotFound) separately from generic errors","Don't cache alert/decision IDs across DB resets or retention windows","Account for retention-based purging when referencing old objects"],"tags":["database","crowdsec","not-found"],"backgroundTag":"record-not-found","analyzedSha":"909b5157986a2b2c2163300fdaef5ed01289f7d2","analyzedAt":"2026-09-06T12:27:26.012Z","contentChangedAt":"2026-09-06T12:27:26.012Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}