{"record":{"id":"6eac729798a0df26","repo":"crowdsecurity/crowdsec","slug":"querying-pending-machines-w-w","errorCode":null,"errorMessage":"querying pending machines: %w: %w","messagePattern":"querying pending machines: %w: %w","errorType":"exception","errorClass":"QueryFail","httpStatus":null,"severity":"error","filePath":"pkg/database/machines.go","lineNumber":156,"sourceCode":"\nfunc (c *Client) ValidateMachine(ctx context.Context, machineID string) error {\n\trets, err := c.Ent.Machine.Update().Where(machine.MachineIdEQ(machineID)).SetIsValidated(true).Save(ctx)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"validating machine: %w: %w\", err, UpdateFail)\n\t}\n\n\tif rets == 0 {\n\t\treturn errors.New(\"machine not found\")\n\t}\n\n\treturn nil\n}\n\nfunc (c *Client) QueryPendingMachine(ctx context.Context) ([]*ent.Machine, error) {\n\tmachines, err := c.Ent.Machine.Query().Where(machine.IsValidatedEQ(false)).All(ctx)\n\tif err != nil {\n\t\tc.Log.Warningf(\"QueryPendingMachine : %s\", err)\n\t\treturn nil, fmt.Errorf(\"querying pending machines: %w: %w\", err, QueryFail)\n\t}\n\n\treturn machines, nil\n}\n\nfunc (c *Client) DeleteWatcher(ctx context.Context, name string) error {\n\tnbDeleted, err := c.Ent.Machine.\n\t\tDelete().\n\t\tWhere(machine.MachineIdEQ(name)).\n\t\tExec(ctx)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif nbDeleted == 0 {\n\t\treturn &MachineNotFoundError{MachineID: name}\n\t}\n","sourceCodeStart":138,"sourceCodeEnd":174,"githubUrl":"https://github.com/crowdsecurity/crowdsec/blob/909b5157986a2b2c2163300fdaef5ed01289f7d2/pkg/database/machines.go#L138-L174","documentation":"QueryPendingMachine wraps QueryFail when querying all machines with is_validated=false fails in the ent layer. This read backs the LAPI prune routine that expires unvalidated pending machines. The wrapped err contains the SQL-level reason.","triggerScenarios":"Client.QueryPendingMachine, invoked from the prune job, hits an unavailable DB, a locked SQLite file, or a machines table missing the is_validated column (schema drift).","commonSituations":"LAPI started before DB is ready (container orchestration race); DB schema migrated backwards; long-running backup holding the SQLite lock; remote DB network blip.","solutions":["Inspect the wrapped error and the 'QueryPendingMachine : <err>' warning log","Ensure the DB is reachable before LAPI starts (depends_on/healthcheck in containers)","Run `cscli migration` to align schema with the binary","Check SQLite lock contention; move to Postgres/MySQL for concurrent writers","Verify prune job config if it fires during maintenance windows"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// wait for DB before starting prune-dependent jobs\nfor i := 0; i < 5; i++ { if dbOK(ctx) { break }; time.Sleep(2*time.Second) }","typeGuard":null,"tryCatchPattern":"pending, err := db.QueryPendingMachine(ctx)\nif err != nil {\n    log.Warnf(\"prune skipped: %v\", err)\n    return // retry next tick; do not crash the job\n}","preventionTips":["Delay LAPI startup until the DB accepts connections","Do not downgrade the binary below the migrated schema","Schedule prune away from backup windows that lock SQLite","Consider MySQL/Postgres when multiple processes share the DB"],"tags":["database","query-failed","prune","crowdsec"],"backgroundTag":"database-query-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"}