{"record":{"id":"24953eeba46a237a","repo":"crowdsecurity/crowdsec","slug":"delete-lock-w-w","errorCode":null,"errorMessage":"delete lock: %w: %w","messagePattern":"delete lock: %w: %w","errorType":"exception","errorClass":"DeleteFail","httpStatus":null,"severity":"error","filePath":"pkg/database/lock.go","lineNumber":41,"sourceCode":"\t\tSetCreatedAt(time.Now().UTC()).\n\t\tSave(ctx)\n\n\tif ent.IsConstraintError(err) {\n\t\treturn err\n\t}\n\n\tif err != nil {\n\t\treturn fmt.Errorf(\"insert lock: %w: %w\", err, InsertFail)\n\t}\n\n\treturn nil\n}\n\nfunc (c *Client) ReleaseLock(ctx context.Context, name string) error {\n\tlog.Debugf(\"releasing lock %s\", name)\n\t_, err := c.Ent.Lock.Delete().Where(lock.NameEQ(name)).Exec(ctx)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"delete lock: %w: %w\", err, DeleteFail)\n\t}\n\n\treturn nil\n}\n\nfunc (c *Client) ReleaseLockWithTimeout(ctx context.Context, name string, timeout int) error {\n\tlog.Debugf(\"releasing lock %s with timeout of %d minutes\", name, timeout)\n\n\t_, err := c.Ent.Lock.Delete().Where(\n\t\tlock.NameEQ(name),\n\t\tlock.CreatedAtLT(time.Now().UTC().Add(-time.Duration(timeout)*time.Minute)),\n\t).Exec(ctx)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"delete lock: %w: %w\", err, DeleteFail)\n\t}\n\n\treturn nil\n}","sourceCodeStart":23,"sourceCodeEnd":59,"githubUrl":"https://github.com/crowdsecurity/crowdsec/blob/909b5157986a2b2c2163300fdaef5ed01289f7d2/pkg/database/lock.go#L23-L59","documentation":"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.","triggerScenarios":"`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.","commonSituations":"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.","solutions":["Verify DB connectivity; a leaked lock row can be removed manually: `DELETE FROM locks WHERE name='...'`","Retry ReleaseLock — deletion is idempotent","Inspect wrapped driver error for table/permission issues","Ensure the process shutdown path gives the DB time to flush before exit"],"exampleFix":"// manual recovery\nsqlite3 /var/lib/crowdsec/data/crowdsec.db \"DELETE FROM locks WHERE name='CapiPull';\"","handlingStrategy":"try-catch","validationCode":"exists, _ := c.Ent.Lock.Query().Where(lock.NameEQ(name)).Exist(ctx) // check before release","typeGuard":null,"tryCatchPattern":"if err := c.ReleaseLock(ctx, name); err != nil {\n    log.Warnf(\"lock %s may be leaked: %v\", name, err)\n    // schedule manual cleanup\n}","preventionTips":["Always defer ReleaseLock right after AcquireLock succeeds","Alert on leaked lock rows in the locks table","Give shutdown handlers enough time to reach the DB"],"tags":["database","locking","ent"],"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-14T00:17:10.932Z"}