Der Handler protokollierte nur die Klasse der untersten Ursache. Der Schreibausfall vom 2026-10-21 stand damit als org.h2.jdbc.JdbcSQLNonTransientConnectionException im Journal und sonst nichts — eine Klasse, die bei H2 unter anderem DATABASE_IS_CLOSED (90098), OUT_OF_MEMORY (90108), FILE_CORRUPTED_1 (90030) und DATABASE_CALLED_AT_SHUTDOWN (90121) zusammenfasst, also Zustände mit völlig verschiedenen Konsequenzen für den Betrieb.
Die Zeile nennt jetzt die ganze Kette der Exception-Klassen und bei einem Datenbankfehler sqlState und errorCode des Treibers:
Meldungen bleiben 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.
Dies ist das getrennt gehaltene Gegenstück zu werkjournal PR#13. Dort wurde der H2-Verbindungslebenszyklus gehärtet, die Ursache des Vorfalls aber ausdrücklich nicht belegt. Dieser Branch liefert das Mittel, sie beim nächsten Auftreten zu belegen statt zu raten.
Entscheidungen
Die ganze Kette, nicht nur die unterste Klasse. Die Untersuchung in PR#13 musste aus genau einer Klasse rekonstruieren, was passiert war. Dass es kein Speichermangel war — naheliegend bei -Xmx384m — ließ sich ausschließlich daran festmachen, dass unter der H2-Klasse kein java.lang.OutOfMemoryError stand. Die Kette ist also der Teil, der trennt.
Der letzte Datenbankfehler der Kette, nicht der erste. Spring und jOOQ hüllen den Treiberfehler in eigene SQLException-Ableitungen, deren Code und Zustand nichts aussagen.
Der Fehlercode zusätzlich zum SQLState. H2 2.4.240 vergibt für seine 90xxx-Fehler den Fehlercode selbst als SQLState; DATABASE_IS_CLOSED meldet sqlState=90098 statt einer 08er-Verbindungsklasse. Aus der Exception-Klasse auf eine SQLState-Klasse zu schließen, führt in die Irre — eine Annahme, die in der Untersuchung zu PR#13 widerlegt wurde.
Was an diesem Branch noch zu tun war
Der Commit lag seit dem 2026-10-21 fertig, aber unvollständig nach Projektkonvention. Ergänzt wurden: Micro-Version (0.1.127-SNAPSHOT), Nachweis unter docs/implementation/, Statuspflege im Werkbaum.
Inhaltlich korrigiert: der Kommentar im Code behauptete, die Klasse nenne „die SQLState-Klasse, aber nicht den Zustand". Für H2 2.4.240 ist das falsch — sie nennt beides nicht. Der Test führte dazu passend ein erfundenes sqlState=08003 neben errorCode=90098; er trägt jetzt die tatsächliche Form des Vorfalls (90098/90098), und ein zweiter, knapper Fall belegt mit ERROR_OPENING_DATABASE_1 (08000/8000), dass beide Felder getrennt gelesen werden.
Keine Migration, kein Schemaeingriff, keine Änderung an der Meldung für den Nutzer.
Nachweise
FailureDetailTest: ein Datenbankfehler in der Form des Vorfalls 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, werden beide getrennt gelesen; eine Störung ohne Datenbankursache nennt nur ihre Klassen.
Die Ursache des Vorfalls selbst. #h2-failure-proof steht im Werkbaum auf [~] und bleibt offen, bis ein tatsächlicher Vorfall mit diesen Angaben zugeordnet ist. Offen bleibt insbesondere, wieso Lesen durchgehend funktionierte, während jeder Schreibvorgang scheiterte — das passt zu keinem der eingegrenzten Kandidaten.
Der Handler protokollierte nur die Klasse der untersten Ursache. Der Schreibausfall vom 2026-10-21 stand damit als `org.h2.jdbc.JdbcSQLNonTransientConnectionException` im Journal und sonst nichts — eine Klasse, die bei H2 unter anderem `DATABASE_IS_CLOSED` (90098), `OUT_OF_MEMORY` (90108), `FILE_CORRUPTED_1` (90030) und `DATABASE_CALLED_AT_SHUTDOWN` (90121) zusammenfasst, also Zustände mit völlig verschiedenen Konsequenzen für den Betrieb.
Die Zeile nennt jetzt die ganze Kette der Exception-Klassen und 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 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.
Dies ist das getrennt gehaltene Gegenstück zu [werkjournal PR#13](https://git.javagil.de/mi/werkjournal/pulls/13). Dort wurde der H2-Verbindungslebenszyklus gehärtet, die Ursache des Vorfalls aber ausdrücklich **nicht** belegt. Dieser Branch liefert das Mittel, sie beim nächsten Auftreten zu belegen statt zu raten.
## Entscheidungen
- **Die ganze Kette, nicht nur die unterste Klasse.** Die Untersuchung in PR#13 musste aus genau einer Klasse rekonstruieren, was passiert war. Dass es kein Speichermangel war — naheliegend bei `-Xmx384m` — ließ sich ausschließlich daran festmachen, dass unter der H2-Klasse kein `java.lang.OutOfMemoryError` stand. Die Kette ist also der Teil, der trennt.
- **Der letzte Datenbankfehler der Kette, nicht der erste.** Spring und jOOQ hüllen den Treiberfehler in eigene `SQLException`-Ableitungen, deren Code und Zustand nichts aussagen.
- **Der Fehlercode zusätzlich zum SQLState.** H2 2.4.240 vergibt für seine 90xxx-Fehler den Fehlercode selbst als SQLState; `DATABASE_IS_CLOSED` meldet `sqlState=90098` statt einer 08er-Verbindungsklasse. Aus der Exception-Klasse auf eine SQLState-Klasse zu schließen, führt in die Irre — eine Annahme, die in der Untersuchung zu PR#13 widerlegt wurde.
## Was an diesem Branch noch zu tun war
Der Commit lag seit dem 2026-10-21 fertig, aber unvollständig nach Projektkonvention. Ergänzt wurden: Micro-Version (0.1.127-SNAPSHOT), Nachweis unter `docs/implementation/`, Statuspflege im Werkbaum.
Inhaltlich korrigiert: der Kommentar im Code behauptete, die Klasse nenne „die SQLState-Klasse, aber nicht den Zustand". Für H2 2.4.240 ist das falsch — sie nennt beides nicht. Der Test führte dazu passend ein erfundenes `sqlState=08003` neben `errorCode=90098`; er trägt jetzt die tatsächliche Form des Vorfalls (`90098`/`90098`), und ein zweiter, knapper Fall belegt mit `ERROR_OPENING_DATABASE_1` (`08000`/`8000`), dass beide Felder getrennt gelesen werden.
Keine Migration, kein Schemaeingriff, keine Änderung an der Meldung für den Nutzer.
## Nachweise
- `FailureDetailTest`: ein Datenbankfehler in der Form des Vorfalls 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, werden beide getrennt gelesen; eine Störung ohne Datenbankursache nennt nur ihre Klassen.
- `JAVA_HOME=~/opt/jdk25 ./tools/ci-jvm --without-firefox` grün: `BUILD SUCCESSFUL in 7m 12s`, 72 Betriebstests.
Details: `docs/implementation/failure-diagnostics.md`.
## Offen
Die Ursache des Vorfalls selbst. `#h2-failure-proof` steht im Werkbaum auf `[~]` und bleibt offen, bis ein tatsächlicher Vorfall mit diesen Angaben zugeordnet ist. Offen bleibt insbesondere, wieso Lesen durchgehend funktionierte, während jeder Schreibvorgang scheiterte — das passt zu keinem der eingegrenzten Kandidaten.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Der Handler protokollierte nur die Klasse der untersten Ursache. Der Schreibausfall vom 2026-10-21
stand damit als `org.h2.jdbc.JdbcSQLNonTransientConnectionException` im Journal und sonst nichts —
eine Klasse, die bei H2 unter anderem DATABASE_IS_CLOSED, OUT_OF_MEMORY, FILE_CORRUPTED_1 und
DATABASE_CALLED_AT_SHUTDOWN zusammenfasst, also Zustände mit völlig verschiedenen Konsequenzen.
Die Zeile nennt jetzt die ganze Kette der Exception-Klassen und bei einem Datenbankfehler
`sqlState` und `errorCode` des Treibers. Meldungen bleiben wie bisher draußen: sie können SQL-Werte
oder Nutzertext enthalten. Die Fehlerkennung bleibt die Brücke zwischen Meldung und Protokollzeile.
## Entscheidungen
- **Die ganze Kette, nicht nur die unterste Klasse.** Die Untersuchung zum
H2-Verbindungslebenszyklus musste aus genau einer Klasse rekonstruieren, was passiert war. Dass
es kein Speichermangel war, ließ sich nur daran festmachen, dass dort kein OutOfMemoryError
stand — die Kette ist also der Teil, der trennt.
- **Der letzte Datenbankfehler der Kette, nicht der erste.** Spring und jOOQ hüllen den
Treiberfehler in eigene SQLException-Ableitungen, deren Code und Zustand nichts aussagen.
- **Der Fehlercode zusätzlich zum SQLState.** H2 2.4.240 vergibt für seine 90xxx-Fehler den
Fehlercode selbst als SQLState; DATABASE_IS_CLOSED meldet sqlState=90098 statt einer
08er-Verbindungsklasse. Aus der Exception-Klasse auf eine SQLState-Klasse zu schließen, führt in
die Irre.
Der Kommentar im Code behauptete bisher, die Klasse nenne „die SQLState-Klasse, aber nicht den
Zustand". Das ist für H2 2.4.240 widerlegt und entsprechend korrigiert; der Test führt jetzt die
tatsächliche Form des Vorfalls statt eines erfundenen 08003.
Keine Migration, kein Schemaeingriff, keine Änderung an der Meldung für den Nutzer.
## Nachweise
- `FailureDetailTest`: ein Datenbankfehler in der Form des Vorfalls nennt sqlState=90098,
errorCode=90098 und beide umhüllenden Klassen, und weder die SQL-Anweisung noch die darin
enthaltene Adresse erscheinen; wo H2 Code und Zustand auseinanderhält (08000/8000), werden beide
getrennt gelesen; eine Störung ohne Datenbankursache nennt nur ihre Klassen.
- `JAVA_HOME=~/opt/jdk25 ./tools/ci-jvm --without-firefox` grün: BUILD SUCCESSFUL in 7m 12s,
72 Betriebstests.
Details: `docs/implementation/failure-diagnostics.md`.
## Offen
Die Ursache des Vorfalls selbst. Der Werkbaum-Knoten `#h2-failure-proof` bleibt offen, bis ein
tatsächlicher Vorfall mit diesen Angaben zugeordnet ist. Offen bleibt insbesondere, wieso Lesen
durchgehend funktionierte, während jeder Schreibvorgang scheiterte.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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.
Der Handler protokollierte nur die Klasse der untersten Ursache. Der Schreibausfall vom 2026-10-21 stand damit als
org.h2.jdbc.JdbcSQLNonTransientConnectionExceptionim Journal und sonst nichts — eine Klasse, die bei H2 unter anderemDATABASE_IS_CLOSED(90098),OUT_OF_MEMORY(90108),FILE_CORRUPTED_1(90030) undDATABASE_CALLED_AT_SHUTDOWN(90121) zusammenfasst, also Zustände mit völlig verschiedenen Konsequenzen für den Betrieb.Die Zeile nennt jetzt die ganze Kette der Exception-Klassen und bei einem Datenbankfehler
sqlStateunderrorCodedes Treibers:Meldungen bleiben 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.
Dies ist das getrennt gehaltene Gegenstück zu werkjournal PR#13. Dort wurde der H2-Verbindungslebenszyklus gehärtet, die Ursache des Vorfalls aber ausdrücklich nicht belegt. Dieser Branch liefert das Mittel, sie beim nächsten Auftreten zu belegen statt zu raten.
Entscheidungen
-Xmx384m— ließ sich ausschließlich daran festmachen, dass unter der H2-Klasse keinjava.lang.OutOfMemoryErrorstand. Die Kette ist also der Teil, der trennt.SQLException-Ableitungen, deren Code und Zustand nichts aussagen.DATABASE_IS_CLOSEDmeldetsqlState=90098statt einer 08er-Verbindungsklasse. Aus der Exception-Klasse auf eine SQLState-Klasse zu schließen, führt in die Irre — eine Annahme, die in der Untersuchung zu PR#13 widerlegt wurde.Was an diesem Branch noch zu tun war
Der Commit lag seit dem 2026-10-21 fertig, aber unvollständig nach Projektkonvention. Ergänzt wurden: Micro-Version (0.1.127-SNAPSHOT), Nachweis unter
docs/implementation/, Statuspflege im Werkbaum.Inhaltlich korrigiert: der Kommentar im Code behauptete, die Klasse nenne „die SQLState-Klasse, aber nicht den Zustand". Für H2 2.4.240 ist das falsch — sie nennt beides nicht. Der Test führte dazu passend ein erfundenes
sqlState=08003nebenerrorCode=90098; er trägt jetzt die tatsächliche Form des Vorfalls (90098/90098), und ein zweiter, knapper Fall belegt mitERROR_OPENING_DATABASE_1(08000/8000), dass beide Felder getrennt gelesen werden.Keine Migration, kein Schemaeingriff, keine Änderung an der Meldung für den Nutzer.
Nachweise
FailureDetailTest: ein Datenbankfehler in der Form des Vorfalls nenntsqlState=90098,errorCode=90098und 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, werden beide getrennt gelesen; eine Störung ohne Datenbankursache nennt nur ihre Klassen.JAVA_HOME=~/opt/jdk25 ./tools/ci-jvm --without-firefoxgrün:BUILD SUCCESSFUL in 7m 12s, 72 Betriebstests.Details:
docs/implementation/failure-diagnostics.md.Offen
Die Ursache des Vorfalls selbst.
#h2-failure-proofsteht im Werkbaum auf[~]und bleibt offen, bis ein tatsächlicher Vorfall mit diesen Angaben zugeordnet ist. Offen bleibt insbesondere, wieso Lesen durchgehend funktionierte, während jeder Schreibvorgang scheiterte — das passt zu keinem der eingegrenzten Kandidaten.🤖 Generated with Claude Code
eeeefae7e1to312a132d14