{"record":{"id":"87c6b597f35d9b44","repo":"crowdsecurity/crowdsec","slug":"unable-to-update-machine-version-in-database-w","errorCode":null,"errorMessage":"unable to update machine version in database: %w","messagePattern":"unable to update machine version in database: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/database/machines.go","lineNumber":229,"sourceCode":"}\n\nfunc (c *Client) UpdateMachineIP(ctx context.Context, ipAddr string, id int) error {\n\t_, err := c.Ent.Machine.UpdateOneID(id).\n\t\tSetIpAddress(ipAddr).\n\t\tSave(ctx)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"unable to update machine IP in database: %w\", err)\n\t}\n\n\treturn nil\n}\n\nfunc (c *Client) UpdateMachineVersion(ctx context.Context, ipAddr string, id int) error {\n\t_, err := c.Ent.Machine.UpdateOneID(id).\n\t\tSetVersion(ipAddr).\n\t\tSave(ctx)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"unable to update machine version in database: %w\", err)\n\t}\n\n\treturn nil\n}\n\nfunc (c *Client) QueryMachinesInactiveSince(ctx context.Context, t time.Time) ([]*ent.Machine, error) {\n\treturn c.Ent.Machine.Query().Where(\n\t\tmachine.Or(\n\t\t\tmachine.And(machine.LastHeartbeatLT(t), machine.IsValidatedEQ(true)),\n\t\t\tmachine.And(machine.LastHeartbeatIsNil(), machine.CreatedAtLT(t)),\n\t\t),\n\t).All(ctx)\n}\n","sourceCodeStart":211,"sourceCodeEnd":243,"githubUrl":"https://github.com/crowdsecurity/crowdsec/blob/909b5157986a2b2c2163300fdaef5ed01289f7d2/pkg/database/machines.go#L211-L243","documentation":"UpdateMachineVersion returns the raw ent error when Machine.UpdateOneID(id).SetVersion(ipAddr).Save(ctx) fails while storing the watcher's crowdsec version. It is invoked from Authenticator during watcher authentication. Same failure modes as the other UpdateOneID callers: missing row (concurrent delete) or DB-level failure. (Note the parameter is misleadingly named ipAddr but carries the version string.)","triggerScenarios":"Authenticator detects a version change and persists it; the update fails because the machine row is gone (prune/delete race) or the DB write fails (lock, down, disk full).","commonSituations":"Watcher upgrading its crowdsec version while its machine entry is being pruned; SQLite contention at scale; DB restart during the auth request.","solutions":["Inspect the wrapped error; handle ent not-found separately from infra failures","Verify the machine still exists and retry once with fresh row data","Check DB health (connectivity, locks, disk) if this recurs across watchers","Keep the machines table consistent: avoid deleting rows while auths are in flight, or accept the benign not-found"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"m, err := db.QueryMachineByID(ctx, machineID)\nif err != nil { return err }\nerr = db.UpdateMachineVersion(ctx, version, m.ID)","typeGuard":null,"tryCatchPattern":"if err := db.UpdateMachineVersion(ctx, version, id); err != nil {\n    if _, qerr := db.QueryMachineByID(ctx, machineID); errors.Is(qerr, database.UserNotExists) {\n        return nil // machine vanished concurrently\n    }\n    return err\n}","preventionTips":["Same discipline as other UpdateOneID calls: fresh lookup, single retry, benign not-found","During crowdsec upgrades expect version-change updates; keep DB writable at that moment","Monitor for frequent not-found races between prune and auth","Keep the underlying ent error in logs for diagnosis"],"tags":["database","update-failed","crowdsec","authenticator"],"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-14T05:17:10.506Z"}