crowdsecurity/crowdsec · error · DeleteFail

delete lock: %w: %w

Error message

delete lock: %w: %w

What it means

The ent DELETE on the lock table failed while releasing the named lock in ReleaseLock. The sentinel DeleteFail is double-wrapped with the driver error; the distributed lock stays held until its TTL/timeout path (ReleaseLockWithTimeout) or manual cleanup intervenes.

Source

Thrown at pkg/database/lock.go:41

		SetCreatedAt(time.Now().UTC()).
		Save(ctx)

	if ent.IsConstraintError(err) {
		return err
	}

	if err != nil {
		return fmt.Errorf("insert lock: %w: %w", err, InsertFail)
	}

	return nil
}

func (c *Client) ReleaseLock(ctx context.Context, name string) error {
	log.Debugf("releasing lock %s", name)
	_, err := c.Ent.Lock.Delete().Where(lock.NameEQ(name)).Exec(ctx)
	if err != nil {
		return fmt.Errorf("delete lock: %w: %w", err, DeleteFail)
	}

	return nil
}

func (c *Client) ReleaseLockWithTimeout(ctx context.Context, name string, timeout int) error {
	log.Debugf("releasing lock %s with timeout of %d minutes", name, timeout)

	_, err := c.Ent.Lock.Delete().Where(
		lock.NameEQ(name),
		lock.CreatedAtLT(time.Now().UTC().Add(-time.Duration(timeout)*time.Minute)),
	).Exec(ctx)
	if err != nil {
		return fmt.Errorf("delete lock: %w: %w", err, DeleteFail)
	}

	return nil
}

View on GitHub (pinned to 909b515798)

Solutions

  1. Verify DB connectivity; a leaked lock row can be removed manually: `DELETE FROM locks WHERE name='...'`
  2. Retry ReleaseLock — deletion is idempotent
  3. Inspect wrapped driver error for table/permission issues
  4. Ensure the process shutdown path gives the DB time to flush before exit

Example fix

// manual recovery
sqlite3 /var/lib/crowdsec/data/crowdsec.db "DELETE FROM locks WHERE name='CapiPull';"
Defensive patterns

Strategy: try-catch

Validate before calling

exists, _ := c.Ent.Lock.Query().Where(lock.NameEQ(name)).Exist(ctx) // check before release

Try / catch

if err := c.ReleaseLock(ctx, name); err != nil {
    log.Warnf("lock %s may be leaked: %v", name, err)
    // schedule manual cleanup
}

Prevention

When it happens

Trigger: `c.Ent.Lock.Delete().Where(lock.NameEQ(name)).Exec(ctx)` returns an error — DB connection lost, ctx canceled, or locks table inaccessible while releasing an acquired lock.

Common situations: CAPI pull finishing while the database is shutting down; network drop between crowdsec and external DB mid-operation; stale lock cleanup hitting a broken connection.

Related errors


AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06). Data as JSON: /api/errors/24953eeba46a237a. Report an issue: GitHub.