[Bug][Infra][Data] Keycloak postgres pg_statistic toast corruption persists after #552 closed — ClearExpiredEvents/session purge failing every 15-min cycle since 02:29Z, repair never run
#561
QA Team — 2026-07-14 ~06:40Z. #552 closed on the node-recovery story (fair — node and Keycloak tier are healthy), but the durable data damage from that incident was left unrepaired and is still failing live:
Current state (verified at filing time):missing chunk number 0 for toast value 131293 in pg_toast_2619 is still recurring in keycloak logs — multiple hits in the last 45 minutes, on the same ~15-minute scheduled-task cycle it has followed since 02:29:51Z. Every ClearExpiredEvents / session-purge run fails, so expired events and sessions have been accumulating for 4+ hours and will keep growing until repaired.
The repair (from #552's thread, unchanged):pg_toast_2619 is pg_statistic's toast table — derived planner statistics, safely rebuildable. As postgres superuser on the keycloak DB:
DELETEFROMpg_statistic;ANALYZE;
(If the DELETE itself trips on the corrupt row: REINDEX TABLE pg_toast.pg_toast_2619; first.)
Afterwards, a one-time pg_dump > /dev/null sweep is cheap insurance that pg_statistic was the only casualty — it was merely the visible one (the table the scheduled task happens to read).
Verification once run: the error stops appearing on the next scheduled cycle (watch ~15 min), and the accumulated EVENT_ENTITY backlog drains.
Refs:#552 (closed — incident that wrote through the dead CIFS mount and caused this), #555 (the alerting gap that let it happen silently).
**QA Team** — 2026-07-14 ~06:40Z. #552 closed on the node-recovery story (fair — node and Keycloak tier are healthy), but the **durable data damage from that incident was left unrepaired** and is still failing live:
**Current state (verified at filing time):** `missing chunk number 0 for toast value 131293 in pg_toast_2619` is still recurring in keycloak logs — multiple hits in the last 45 minutes, on the same ~15-minute scheduled-task cycle it has followed since 02:29:51Z. Every `ClearExpiredEvents` / session-purge run fails, so **expired events and sessions have been accumulating for 4+ hours** and will keep growing until repaired.
**The repair (from #552's thread, unchanged):** `pg_toast_2619` is `pg_statistic`'s toast table — derived planner statistics, safely rebuildable. As postgres superuser on the keycloak DB:
```sql
DELETE FROM pg_statistic;
ANALYZE;
```
(If the DELETE itself trips on the corrupt row: `REINDEX TABLE pg_toast.pg_toast_2619;` first.)
Afterwards, a one-time `pg_dump > /dev/null` sweep is cheap insurance that pg_statistic was the only casualty — it was merely the *visible* one (the table the scheduled task happens to read).
**Verification once run:** the error stops appearing on the next scheduled cycle (watch ~15 min), and the accumulated EVENT_ENTITY backlog drains.
**Refs:** #552 (closed — incident that wrote through the dead CIFS mount and caused this), #555 (the alerting gap that let it happen silently).
QA Team — sweep 2026-07-14 ~17:45Z. Still firing, ~15h after this ticket was opened, and the error has moved.
Latest occurrence, straight off keycloak_keycloak on dreamstream5 at 17:29:50Z today:
ERROR [org.keycloak.services.scheduled.ScheduledTaskRunner] (Timer-0)
Failed to run scheduled task ClearExpiredEvents:
org.hibernate.exception.GenericJDBCException: JDBC exception executing SQL
[ERROR: missing chunk number 0 for toast value 131293 in pg_toast_2619]
[select ee1_0.ID from public.EVENT_ENTITY ee1_0
where ee1_0.REALM_ID=? and ee1_0.EVENT_TIME<?
order by ee1_0.EVENT_TIME fetch first ? rows only for no key update of ee1_0 skip locked]
Caused by: org.postgresql.util.PSQLException:
ERROR: missing chunk number 0 for toast value 131293 in pg_toast_2619
Worth flagging precisely, because it sharpens the diagnosis in this ticket:
pg_toast_2619 is the TOAST table for pg_statistic — so this is the same corruption this ticket already names, now confirmed still present and still unrepaired.
The failing statement is ClearExpiredEvents, Keycloak's scheduled purge of EVENT_ENTITY. It is failing on every cycle, not intermittently.
The consequence nobody has written down yet: while this is broken, expired Keycloak events are never purged, so EVENT_ENTITY grows without bound. We measured keycloak-events ingest at ~113 docs/day; the postgres-side EVENT_ENTITY table has the same problem with no cleanup running at all. This is a slow-motion disk issue on top of the correctness issue — and SERVER's root filesystem hitting 94% (#558, closed today) is a reminder of what that ends in.
The repair is still the same and still has not been run: the planner touching a corrupt pg_statistic toast entry needs ANALYZE on the affected relation to rewrite the stats (or VACUUM FULL pg_statistic / in the worst case REINDEX). Until someone runs it, this fires every 15 minutes indefinitely.
Note this predates and is independent of the dreamstream4 failover in #552 (closed) — that closed on the node recovering, but the database corruption it left behind is what this ticket is about, and it is untouched.
**QA Team** — sweep 2026-07-14 ~17:45Z. **Still firing, ~15h after this ticket was opened, and the error has moved.**
Latest occurrence, straight off `keycloak_keycloak` on dreamstream5 at **17:29:50Z today**:
```
ERROR [org.keycloak.services.scheduled.ScheduledTaskRunner] (Timer-0)
Failed to run scheduled task ClearExpiredEvents:
org.hibernate.exception.GenericJDBCException: JDBC exception executing SQL
[ERROR: missing chunk number 0 for toast value 131293 in pg_toast_2619]
[select ee1_0.ID from public.EVENT_ENTITY ee1_0
where ee1_0.REALM_ID=? and ee1_0.EVENT_TIME<?
order by ee1_0.EVENT_TIME fetch first ? rows only for no key update of ee1_0 skip locked]
Caused by: org.postgresql.util.PSQLException:
ERROR: missing chunk number 0 for toast value 131293 in pg_toast_2619
```
Worth flagging precisely, because it sharpens the diagnosis in this ticket:
- `pg_toast_2619` is the TOAST table for **`pg_statistic`** — so this is the same corruption this ticket already names, now confirmed still present and still unrepaired.
- The failing statement is **`ClearExpiredEvents`**, Keycloak's scheduled purge of `EVENT_ENTITY`. It is failing on *every* cycle, not intermittently.
**The consequence nobody has written down yet:** while this is broken, expired Keycloak events are never purged, so `EVENT_ENTITY` grows without bound. We measured keycloak-events ingest at ~113 docs/day; the postgres-side `EVENT_ENTITY` table has the same problem with no cleanup running at all. This is a slow-motion disk issue on top of the correctness issue — and SERVER's root filesystem hitting 94% (#558, closed today) is a reminder of what that ends in.
The repair is still the same and still has not been run: the planner touching a corrupt `pg_statistic` toast entry needs `ANALYZE` on the affected relation to rewrite the stats (or `VACUUM FULL pg_statistic` / in the worst case `REINDEX`). Until someone runs it, this fires every 15 minutes indefinitely.
Note this predates and is independent of the dreamstream4 failover in #552 (closed) — that closed on the *node* recovering, but the database corruption it left behind is what this ticket is about, and it is untouched.
Audited against origin/master — NOT DONE, and this is the same live defect as #482, not a distinct one. Recommending a merge.
Same corruption, same object, same failing job. Both tickets name the identical error — missing chunk number 0 for toast value 131293 in pg_toast_2619 — including the same toast value 131293, and both fail on ClearExpiredEvents. That's one corruption event observed twice, not a recurring class.
The only artifact in git is the runbook, and it has never been touched since it landed: spikersoft-infrastructure/docs/keycloak-postgres-toast-recovery.md, single commit 8ee2a8d (2026-07-12, PR #49). git log origin/master -- docs/keycloak-postgres-toast-recovery.md returns that one commit and nothing after. git log origin/master --grep='#561' across all four repos returns zero commits.
What genuinely distinguishes the two:#482 (filed 07-12) predates the runbook and carries the SHOW data_checksums; root-cause tail plus the link to #503's confirmed bad RAM on the same host. #561 (filed 07-14) is the post-#552 re-observation and adds the consequence that matters operationally — unbounded EVENT_ENTITY growth, because the purge cycle never completes.
Suggested disposition: keep #482 as the survivor (it holds the runbook link and the bad-RAM root-cause thread), fold this ticket's EVENT_ENTITY-growth note into it, and close this one as a duplicate. I've left both open rather than deciding that unilaterally.
Remaining either way: run the runbook (DELETE FROM pg_statistic; VACUUM pg_statistic; ANALYZE;), confirm the ~60s error stream stops, confirm ClearExpiredEvents completes and EVENT_ENTITY drains, then run SHOW data_checksums;. Git cannot prove any of that — it's a one-time superuser action against a live database. What would settle it: Keycloak service logs showing a clean ClearExpiredEvents cycle, or simply an execution note on the ticket.
That last point is the actual lesson here. This has now been re-verified from scratch at least three times because there is no place where "ran the runbook" gets written down.
Audited against `origin/master` — **NOT DONE, and this is the same live defect as #482, not a distinct one.** Recommending a merge.
**Same corruption, same object, same failing job.** Both tickets name the identical error — `missing chunk number 0 for toast value 131293 in pg_toast_2619` — including the same toast value `131293`, and both fail on `ClearExpiredEvents`. That's one corruption event observed twice, not a recurring class.
**The only artifact in git is the runbook**, and it has never been touched since it landed: `spikersoft-infrastructure/docs/keycloak-postgres-toast-recovery.md`, single commit `8ee2a8d` (2026-07-12, PR #49). `git log origin/master -- docs/keycloak-postgres-toast-recovery.md` returns that one commit and nothing after. `git log origin/master --grep='#561'` across all four repos returns **zero commits**.
**What genuinely distinguishes the two:** #482 (filed 07-12) predates the runbook and carries the `SHOW data_checksums;` root-cause tail plus the link to #503's confirmed bad RAM on the same host. #561 (filed 07-14) is the post-#552 re-observation and adds the consequence that matters operationally — unbounded `EVENT_ENTITY` growth, because the purge cycle never completes.
**Suggested disposition:** keep **#482** as the survivor (it holds the runbook link and the bad-RAM root-cause thread), fold this ticket's `EVENT_ENTITY`-growth note into it, and close this one as a duplicate. I've left both open rather than deciding that unilaterally.
**Remaining either way:** run the runbook (`DELETE FROM pg_statistic; VACUUM pg_statistic; ANALYZE;`), confirm the ~60s error stream stops, confirm `ClearExpiredEvents` completes and `EVENT_ENTITY` drains, then run `SHOW data_checksums;`. Git cannot prove any of that — it's a one-time superuser action against a live database. What would settle it: Keycloak service logs showing a clean `ClearExpiredEvents` cycle, or simply an execution note on the ticket.
That last point is the actual lesson here. This has now been re-verified from scratch at least three times because there is no place where "ran the runbook" gets written down.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
QA Team — 2026-07-14 ~06:40Z. #552 closed on the node-recovery story (fair — node and Keycloak tier are healthy), but the durable data damage from that incident was left unrepaired and is still failing live:
Current state (verified at filing time):
missing chunk number 0 for toast value 131293 in pg_toast_2619is still recurring in keycloak logs — multiple hits in the last 45 minutes, on the same ~15-minute scheduled-task cycle it has followed since 02:29:51Z. EveryClearExpiredEvents/ session-purge run fails, so expired events and sessions have been accumulating for 4+ hours and will keep growing until repaired.The repair (from #552's thread, unchanged):
pg_toast_2619ispg_statistic's toast table — derived planner statistics, safely rebuildable. As postgres superuser on the keycloak DB:(If the DELETE itself trips on the corrupt row:
REINDEX TABLE pg_toast.pg_toast_2619;first.)Afterwards, a one-time
pg_dump > /dev/nullsweep is cheap insurance that pg_statistic was the only casualty — it was merely the visible one (the table the scheduled task happens to read).Verification once run: the error stops appearing on the next scheduled cycle (watch ~15 min), and the accumulated EVENT_ENTITY backlog drains.
Refs: #552 (closed — incident that wrote through the dead CIFS mount and caused this), #555 (the alerting gap that let it happen silently).
QA Team — sweep 2026-07-14 ~17:45Z. Still firing, ~15h after this ticket was opened, and the error has moved.
Latest occurrence, straight off
keycloak_keycloakon dreamstream5 at 17:29:50Z today:Worth flagging precisely, because it sharpens the diagnosis in this ticket:
pg_toast_2619is the TOAST table forpg_statistic— so this is the same corruption this ticket already names, now confirmed still present and still unrepaired.ClearExpiredEvents, Keycloak's scheduled purge ofEVENT_ENTITY. It is failing on every cycle, not intermittently.The consequence nobody has written down yet: while this is broken, expired Keycloak events are never purged, so
EVENT_ENTITYgrows without bound. We measured keycloak-events ingest at ~113 docs/day; the postgres-sideEVENT_ENTITYtable has the same problem with no cleanup running at all. This is a slow-motion disk issue on top of the correctness issue — and SERVER's root filesystem hitting 94% (#558, closed today) is a reminder of what that ends in.The repair is still the same and still has not been run: the planner touching a corrupt
pg_statistictoast entry needsANALYZEon the affected relation to rewrite the stats (orVACUUM FULL pg_statistic/ in the worst caseREINDEX). Until someone runs it, this fires every 15 minutes indefinitely.Note this predates and is independent of the dreamstream4 failover in #552 (closed) — that closed on the node recovering, but the database corruption it left behind is what this ticket is about, and it is untouched.
Audited against
origin/master— NOT DONE, and this is the same live defect as #482, not a distinct one. Recommending a merge.Same corruption, same object, same failing job. Both tickets name the identical error —
missing chunk number 0 for toast value 131293 in pg_toast_2619— including the same toast value131293, and both fail onClearExpiredEvents. That's one corruption event observed twice, not a recurring class.The only artifact in git is the runbook, and it has never been touched since it landed:
spikersoft-infrastructure/docs/keycloak-postgres-toast-recovery.md, single commit8ee2a8d(2026-07-12, PR #49).git log origin/master -- docs/keycloak-postgres-toast-recovery.mdreturns that one commit and nothing after.git log origin/master --grep='#561'across all four repos returns zero commits.What genuinely distinguishes the two: #482 (filed 07-12) predates the runbook and carries the
SHOW data_checksums;root-cause tail plus the link to #503's confirmed bad RAM on the same host. #561 (filed 07-14) is the post-#552 re-observation and adds the consequence that matters operationally — unboundedEVENT_ENTITYgrowth, because the purge cycle never completes.Suggested disposition: keep #482 as the survivor (it holds the runbook link and the bad-RAM root-cause thread), fold this ticket's
EVENT_ENTITY-growth note into it, and close this one as a duplicate. I've left both open rather than deciding that unilaterally.Remaining either way: run the runbook (
DELETE FROM pg_statistic; VACUUM pg_statistic; ANALYZE;), confirm the ~60s error stream stops, confirmClearExpiredEventscompletes andEVENT_ENTITYdrains, then runSHOW data_checksums;. Git cannot prove any of that — it's a one-time superuser action against a live database. What would settle it: Keycloak service logs showing a cleanClearExpiredEventscycle, or simply an execution note on the ticket.That last point is the actual lesson here. This has now been re-verified from scratch at least three times because there is no place where "ran the runbook" gets written down.