{"record":{"id":"c7cc7ae71d16ba5b","repo":"crowdsecurity/crowdsec","slug":"validating-machine-w-w","errorCode":null,"errorMessage":"validating machine: %w: %w","messagePattern":"validating machine: %w: %w","errorType":"exception","errorClass":"UpdateFail","httpStatus":null,"severity":"error","filePath":"pkg/database/machines.go","lineNumber":142,"sourceCode":"\t\treturn &ent.Machine{}, fmt.Errorf(\"user '%s': %w\", machineID, UserNotExists)\n\t}\n\n\treturn machine, nil\n}\n\nfunc (c *Client) ListMachines(ctx context.Context) ([]*ent.Machine, error) {\n\tmachines, err := c.Ent.Machine.Query().All(ctx)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"listing machines: %w: %w\", err, QueryFail)\n\t}\n\n\treturn machines, nil\n}\n\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}","sourceCodeStart":124,"sourceCodeEnd":160,"githubUrl":"https://github.com/crowdsecurity/crowdsec/blob/909b5157986a2b2c2163300fdaef5ed01289f7d2/pkg/database/machines.go#L124-L160","documentation":"ValidateMachine wraps the UpdateFail sentinel when the bulk `Machine.Update().Where(...).SetIsValidated(true).Save(ctx)` fails. Separately, if the update succeeds but touches 0 rows, a plain error 'machine not found' is returned. So this specific error is a DB write failure while validating a watcher, not a missing machine.","triggerScenarios":"Calling ValidateMachine (LAPI 'validate' controller, `cscli machines validate <name>`) with the DB refusing the UPDATE: connection lost, SQLite locked by another process, schema mismatch on the machines table.","commonSituations":"Concurrent LAPI writers holding the SQLite write lock; disk full preventing the update; schema drift after partial upgrade; remote DB credentials rotated.","solutions":["Read the wrapped error for the SQL-level cause","Retry the validation once the DB is writable: `cscli machines validate <name>`","Check for competing processes locking the SQLite DB (backup jobs, second LAPI)","Verify schema version matches: `cscli migration`","Confirm the machine exists first via `cscli machines list` to distinguish from 'machine not found'"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// verify the machine exists before validating\nrets, _ := db.QueryMachineByID(ctx, machineID)\nif rets == nil || rets.ID == 0 {\n    return fmt.Errorf(\"machine %q not found\", machineID)\n}","typeGuard":null,"tryCatchPattern":"if err := db.ValidateMachine(ctx, machineID); err != nil {\n    if err.Error() == \"machine not found\" {\n        // distinct case: unknown id\n    } else if errors.Is(err, database.UpdateFail) {\n        // DB write failure: inspect cause, retry\n    }\n    return err\n}","preventionTips":["Validate only machines listed by `cscli machines list`","Serialize DB writers or move to a client/server DB to avoid SQLite lock errors","Keep free disk headroom on the DB volume","Run schema migrations immediately after binary upgrades"],"tags":["database","update-failed","crowdsec","lapi"],"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"}