# Was eine UI-Störung im Protokoll nennen darf Am 2026-10-21 scheiterte in Produktion jeder Schreibvorgang. Im Journal stand dazu genau eine Zeile: UI failure 7f3a21c4 (org.h2.jdbc.JdbcSQLNonTransientConnectionException) Mehr gab es nicht. `UiErrorConfiguration` protokollierte die Klasse der untersten Ursache und sonst nichts — bewusst, denn Exception-Meldungen können SQL-Werte oder Nutzertext enthalten. Die Zurückhaltung war richtig, die Auswahl zu eng: eine Klasse allein unterscheidet keine zwei Datenbankfehler voneinander. ## Warum die Klasse allein nicht reicht Die Untersuchung zu [H2-Verbindungslebenszyklus](h2-connection-lifecycle.md) musste die Ursache aus genau dieser einen Zeile rekonstruieren. Dabei trat zutage, wie viel an Information fehlte: - **Der SQLState hilft bei H2 nicht weiter, wo man ihn vermuten würde.** H2 2.4.240 vergibt für seine 90xxx-Fehler den Fehlercode selbst als SQLState. `DATABASE_IS_CLOSED` meldet `sqlState=90098`, nicht eine 08er-Verbindungsklasse. Aus der Exception-Klasse auf eine SQLState-Klasse zu schließen, führt in die Irre; der Treibercode ist die Angabe, die trennt. - **Die Exception-Klasse fasst sehr Verschiedenes zusammen.** `JdbcSQLNonTransientConnectionException` steht unter anderem für `DATABASE_IS_CLOSED` (90098), `OUT_OF_MEMORY` (90108), `FILE_CORRUPTED_1` (90030) und `DATABASE_CALLED_AT_SHUTDOWN` (90121) — Zustände mit völlig verschiedenen Konsequenzen für den Betrieb. - **Die Kette trennt, was die unterste Klasse verbirgt.** Ein erschöpfter Heap erreicht die Anwendung als `JdbcSQLNonTransientConnectionException` mit `java.lang.OutOfMemoryError` darunter; ein Schreibfehler der Ablage als `JdbcSQLNonTransientException` über einem `MVStoreException` oder `IOException`. Nur die Kette zeigt diesen Unterschied. Die Rekonstruktion kam damit bis zu einer Aussage über die *Form* der Exception und blieb dort stehen. Mit den Angaben dieser Umsetzung wäre sie eine Zuordnung gewesen. ## Was die Zeile jetzt nennt `failureDetail` setzt die Zeile aus der Kette der Exception-Klassen zusammen und ergänzt bei einem Datenbankfehler `sqlState` und `errorCode` des Treibers: UI failure 7f3a21c4 (java.lang.RuntimeException <- org.jooq.exception.DataAccessException <- org.h2.jdbc.JdbcSQLNonTransientConnectionException sqlState=90098 errorCode=90098) **Meldungen bleiben weiterhin draußen.** Das war der Grund der ursprünglichen Zurückhaltung und gilt unverändert: Klassennamen, SQLState und Fehlercode sind Werte des Treibers, keine Werte aus den Daten. Die Fehlerkennung, die der Nutzer sieht, bleibt unverändert die Brücke zwischen Meldung und Protokollzeile. Genommen wird die letzte `SQLException` der Kette, nicht die erste: Spring und jOOQ hüllen den Treiberfehler in eigene `SQLException`-Ableitungen, deren Code und Zustand nichts aussagen. Ohne Datenbankfehler in der Kette nennt die Zeile nur die Klassen. Die Kette ist weiterhin auf sechzehn Glieder begrenzt, wie schon zuvor beim Suchen nach `RecordConflict` und `RecordNotFound`. Für die beobachteten Ketten reicht das deutlich. ## Nachweise - `FailureDetailTest`: ein Datenbankfehler in der Form des Vorfalls vom 2026-10-21 nennt `sqlState=90098`, `errorCode=90098` und beide umhüllenden Klassen, und weder die SQL-Anweisung noch die darin enthaltene Adresse erscheinen in der Zeile; wo H2 Code und Zustand auseinanderhält (`ERROR_OPENING_DATABASE_1`, `08000`/`8000`), werden beide getrennt gelesen; eine Störung ohne Datenbankursache nennt nur ihre Klassen.