ory/kratos · error

An error occurred while cleaning up expired data

Error message

An error occurred while cleaning up expired data

What it means

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).

Solutions

  1. Inspect the wrapped cause below this message to see which table/statement failed.
  2. Grant DELETE (and SELECT) on the Kratos tables to the configured DB user.
  3. Reduce database_cleanup_batch_size and/or increase sleep time to shorten transactions and avoid lock timeouts.
  4. Re-run the cleanup — it is resumable since it deletes in batches; check network stability for cron hosts.

Example fix

// before (huge single batches, lock timeouts)
database_cleanup_batch_size: 100000
// after
database_cleanup_batch_size: 500
Defensive patterns

Strategy: retry

Validate before calling

// Confirm the DB user may delete before the run:
var has bool
_ = db.QueryRow(`SELECT has_table_privilege(current_user, 'sessions', 'DELETE')`).Scan(&has)
if !has { return errors.New("DB user lacks DELETE privilege") }

Try / catch

if out, err := exec.Command("kratos", "cleanup", "sql").CombinedOutput(); err != nil {
    if strings.Contains(string(out), "while cleaning up expired data") {
        log.Error("CleanupDatabase failed; inspect wrapped cause, lower batch size, re-run", "out", string(out))
    }
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: Database query failed: Internal Server Error 500s wrapping SQL, Prisma, and connection failures — what to check first — this error's family across 16 libraries.

Related errors


AI-assisted analysis of ory/kratos@b86338da04 (2026-09-07). Data as JSON: /api/errors/5efb0ef12575d82b. Report an issue: GitHub.

Appendix: source

Thrown at cmd/cleanup/handler.go:63

		return errors.New(`required config value "dsn" was not set`)
	} else if err != nil {
		return errors.Wrap(err, "An error occurred initializing cleanup")
	}

	err = d.Init(cmd.Context(), &contextx.Default{})
	if err != nil {
		return errors.Wrap(err, "An error occurred initializing cleanup")
	}

	keepLast := flagx.MustGetDuration(cmd, "keep-last")

	err = d.Persister().CleanupDatabase(
		cmd.Context(),
		d.Config().DatabaseCleanupSleepTables(cmd.Context()),
		keepLast,
		d.Config().DatabaseCleanupBatchSize(cmd.Context()))
	if err != nil {
		return errors.Wrap(err, "An error occurred while cleaning up expired data")
	}

	return nil
}

View on GitHub (pinned to b86338da04)