{"record":{"id":"79cdee5b4da9f9ef","repo":"crowdsecurity/crowdsec","slug":"unable-to-update-machine-last-pull-in-database-w","errorCode":null,"errorMessage":"unable to update machine last pull in database: %w","messagePattern":"unable to update machine last pull in database: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/database/bouncers.go","lineNumber":137,"sourceCode":"\tids := make([]int, len(bouncers))\n\tfor i, b := range bouncers {\n\t\tids[i] = b.ID\n\t}\n\n\tnbDeleted, err := c.Ent.Bouncer.Delete().Where(bouncer.IDIn(ids...)).Exec(ctx)\n\tif err != nil {\n\t\treturn nbDeleted, fmt.Errorf(\"unable to delete bouncers: %w\", err)\n\t}\n\n\treturn nbDeleted, nil\n}\n\nfunc (c *Client) UpdateBouncerLastPull(ctx context.Context, lastPull time.Time, id int) error {\n\t_, err := c.Ent.Bouncer.UpdateOneID(id).\n\t\tSetLastPull(lastPull).\n\t\tSave(ctx)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"unable to update machine last pull in database: %w\", err)\n\t}\n\n\treturn nil\n}\n\nfunc (c *Client) UpdateBouncerStreamPull(ctx context.Context, lastPull time.Time, streamCursor int, id int) error {\n\t_, err := c.Ent.Bouncer.UpdateOneID(id).\n\t\tSetLastPull(lastPull).\n\t\tSetStreamCursor(streamCursor).\n\t\tSave(ctx)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"unable to update bouncer stream pull in database: %w\", err)\n\t}\n\n\treturn nil\n}\n\nfunc (c *Client) UpdateBouncerIP(ctx context.Context, ipAddr string, id int) error {","sourceCodeStart":119,"sourceCodeEnd":155,"githubUrl":"https://github.com/crowdsecurity/crowdsec/blob/909b5157986a2b2c2163300fdaef5ed01289f7d2/pkg/database/bouncers.go#L119-L155","documentation":"UpdateBouncerLastPull wraps a failed ent update of a bouncer's last_pull timestamp. It calls UpdateOneID(id).SetLastPull(...).Save(ctx); any driver error, missing row, or cancelled context surfaces wrapped in this message. Called by GetDecision after a bouncer pulls decisions.","triggerScenarios":"The bouncer ID no longer exists in the bouncers table, the database is unreachable/locked, or the request context was cancelled before the UPDATE committed.","commonSituations":"Bouncer deleted by prune while it was still pulling decisions, SQLite 'database is locked' under concurrent LAPI traffic, transient MySQL connection reset.","solutions":["Confirm the bouncer still exists (it may have been pruned or deleted between auth and update)","Check for SQLite lock contention from other crowdsec processes; consider WAL mode or retrying","Inspect the wrapped driver error and retry transient failures","Verify the request context is not being cancelled early by the HTTP server"],"exampleFix":"// before\n_, err := c.Ent.Bouncer.UpdateOneID(id).SetLastPull(lastPull).Save(ctx)\nif err != nil {\n\treturn fmt.Errorf(\"unable to update machine last pull in database: %w\", err)\n}\n// after\nnb, err := c.Ent.Bouncer.UpdateOneID(id).SetLastPull(lastPull).Save(ctx)\nif ent.IsNotFound(err) {\n\treturn fmt.Errorf(\"bouncer %d no longer exists\", id)\n} else if err != nil {\n\treturn fmt.Errorf(\"unable to update machine last pull in database: %w\", err)\n}","handlingStrategy":"try-catch","validationCode":"// before calling: ensure the bouncer exists\nexists, err := c.BouncerExistsByID(ctx, id)\nif err != nil || !exists { return }","typeGuard":null,"tryCatchPattern":"if err := c.UpdateBouncerLastPull(ctx, time.Now(), id); err != nil {\n\tif ent.IsNotFound(errors.Unwrap(err)) { /* bouncer pruned; re-register or skip */ }\n\tlog.Warnf(\"last pull update failed: %v\", err)\n}","preventionTips":["Re-fetch the bouncer ID from auth result rather than caching stale IDs","Enable WAL mode for concurrent LAPI traffic","Treat missing-row errors as 'bouncer pruned' not fatal","Keep LAPI request contexts alive until DB writes finish"],"tags":["database","ent","sqlite","bouncers"],"backgroundTag":"database-write-failed","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"}