{"record":{"id":"5efb0ef12575d82b","repo":"ory/kratos","slug":"an-error-occurred-while-cleaning-up-expired-data","errorCode":null,"errorMessage":"An error occurred while cleaning up expired data","messagePattern":"An error occurred while cleaning up expired data","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/cleanup/handler.go","lineNumber":63,"sourceCode":"\t\treturn errors.New(`required config value \"dsn\" was not set`)\n\t} else if err != nil {\n\t\treturn errors.Wrap(err, \"An error occurred initializing cleanup\")\n\t}\n\n\terr = d.Init(cmd.Context(), &contextx.Default{})\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"An error occurred initializing cleanup\")\n\t}\n\n\tkeepLast := flagx.MustGetDuration(cmd, \"keep-last\")\n\n\terr = d.Persister().CleanupDatabase(\n\t\tcmd.Context(),\n\t\td.Config().DatabaseCleanupSleepTables(cmd.Context()),\n\t\tkeepLast,\n\t\td.Config().DatabaseCleanupBatchSize(cmd.Context()))\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"An error occurred while cleaning up expired data\")\n\t}\n\n\treturn nil\n}\n","sourceCodeStart":45,"sourceCodeEnd":68,"githubUrl":"https://github.com/ory/kratos/blob/b86338da04a040247a07f46100a86dcfb3875909/cmd/cleanup/handler.go#L45-L68","documentation":"CleanupSQL wraps errors from d.Persister().CleanupDatabase with this message. CleanupDatabase deletes expired session/token rows in batches according to the configured sleep-tables and batch size; a failure here is a runtime database error during the deletion queries (lock timeouts, cancelled statements, permission issues).","triggerScenarios":"The CleanupDatabase call returns an error mid-run: statement timeout/lock wait timeout on large tables, the DB user lacks DELETE permission, connection dropped during the batch loop, or invalid batch-size/sleep-table config.","commonSituations":"Running cleanup against a production DB with heavy contention; DB role without DELETE grants; very large expired-data backlog causing long-running statements that get killed; network interruptions in long cron jobs.","solutions":["Inspect the wrapped cause below this message to see which table/statement failed.","Grant DELETE (and SELECT) on the Kratos tables to the configured DB user.","Reduce database_cleanup_batch_size and/or increase sleep time to shorten transactions and avoid lock timeouts.","Re-run the cleanup — it is resumable since it deletes in batches; check network stability for cron hosts."],"exampleFix":"// before (huge single batches, lock timeouts)\ndatabase_cleanup_batch_size: 100000\n// after\ndatabase_cleanup_batch_size: 500","handlingStrategy":"retry","validationCode":"// Confirm the DB user may delete before the run:\nvar has bool\n_ = db.QueryRow(`SELECT has_table_privilege(current_user, 'sessions', 'DELETE')`).Scan(&has)\nif !has { return errors.New(\"DB user lacks DELETE privilege\") }","typeGuard":null,"tryCatchPattern":"if out, err := exec.Command(\"kratos\", \"cleanup\", \"sql\").CombinedOutput(); err != nil {\n    if strings.Contains(string(out), \"while cleaning up expired data\") {\n        log.Error(\"CleanupDatabase failed; inspect wrapped cause, lower batch size, re-run\", \"out\", string(out))\n    }\n}","preventionTips":["Grant DELETE/SELECT on all Kratos tables to the cleanup DB user.","Keep database_cleanup_batch_size modest (hundreds, not hundreds of thousands) to avoid lock timeouts.","Schedule cleanup off-peak and ensure cron hosts have stable DB connectivity.","Re-run after transient failures — batched deletion is resumable."],"tags":["database","cleanup","expired-data","cli"],"backgroundTag":"database-query-failed","analyzedSha":"b86338da04a040247a07f46100a86dcfb3875909","analyzedAt":"2026-09-07T15:58:15.934Z","contentChangedAt":"2026-09-07T15:58:15.934Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}