crowdsecurity/crowdsec · error
unable to update bouncer stream pull in database: %w
Error message
unable to update bouncer stream pull in database: %w
What it means
UpdateBouncerStreamPull wraps a failed ent update setting last_pull and the stream cursor on a bouncer row. Same mechanics as the last-pull update but also persists streamCursor; failures are wrapped with this message. Called by StreamDecision.
Source
Thrown at pkg/database/bouncers.go:149
func (c *Client) UpdateBouncerLastPull(ctx context.Context, lastPull time.Time, id int) error {
_, err := c.Ent.Bouncer.UpdateOneID(id).
SetLastPull(lastPull).
Save(ctx)
if err != nil {
return fmt.Errorf("unable to update machine last pull in database: %w", err)
}
return nil
}
func (c *Client) UpdateBouncerStreamPull(ctx context.Context, lastPull time.Time, streamCursor int, id int) error {
_, err := c.Ent.Bouncer.UpdateOneID(id).
SetLastPull(lastPull).
SetStreamCursor(streamCursor).
Save(ctx)
if err != nil {
return fmt.Errorf("unable to update bouncer stream pull in database: %w", err)
}
return nil
}
func (c *Client) UpdateBouncerIP(ctx context.Context, ipAddr string, id int) error {
_, err := c.Ent.Bouncer.UpdateOneID(id).SetIPAddress(ipAddr).Save(ctx)
if err != nil {
return fmt.Errorf("unable to update bouncer ip address in database: %w", err)
}
return nil
}
func (c *Client) UpdateBouncerTypeAndVersion(ctx context.Context, bType string, version string, id int) error {
_, err := c.Ent.Bouncer.UpdateOneID(id).SetVersion(version).SetType(bType).Save(ctx)
if err != nil {
return fmt.Errorf("unable to update bouncer type and version in database: %w", err)View on GitHub (pinned to 909b515798)
Solutions
- Check SQLite lock contention / enable WAL mode for concurrent stream bouncers
- Verify the bouncer was not deleted concurrently (ent.IsNotFound on the wrapped error)
- Retry the update on transient driver errors
- Ensure the request context survives the stream handler duration
Defensive patterns
Strategy: retry
Validate before calling
// ensure bouncer still exists before stream-cursor update
if n, _ := c.Ent.Bouncer.Query().Where(bouncer.ID(id)).Count(ctx); n == 0 { return } Try / catch
err := c.UpdateBouncerStreamPull(ctx, lastPull, cursor, id)
if errors.Is(errors.Unwrap(err), sqlite.ErrLocked) {
time.Sleep(backoff); retry()
} Prevention
- Enable WAL mode for many concurrent stream bouncers
- Use short, retried transactions for cursor updates
- Prune conservatively so live bouncers aren't deleted
- Watch for 'database is locked' in logs
When it happens
Trigger: Bouncer row missing (deleted concurrently), database locked or unreachable, context cancelled mid-update.
Common situations: Stream-mode bouncers polling frequently on a busy SQLite file hitting 'database is locked'; bouncer pruned while its stream session is live.
Related errors
- unable to delete bouncers: %w
- unable to update machine last pull in database: %w
- while getting allowlist %s: %s
- unable to update bouncer ip address in database: %w
- unable to update bouncer type and version in database: %w
AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06).
Data as JSON: /api/errors/5beb9d4bcc4c7494.
Report an issue: GitHub.