JS-IT ← Alle Notizen
27. Februar 2026

CI-Build stirbt an Out-of-Memory — den wahren Schuldigen im GC-Log lesen

Ein Build bricht mit Exit-Code 137 ab. Der erste Verdacht fällt auf den Compiler — das Speicher-Log erzählt eine andere Geschichte.

HeapOOMGC pause 812ms — allocation failureretained: cache 1.4 GB · nie geleert→ nicht der Compiler, die Appnach dem Fix
Nicht der Compiler sprengt den Speicher, sondern gehaltene Objekte — sichtbar erst im GC-Log.

Das Symptom

Der Build läuft lokal durch, im CI stirbt er mit Exit-Code 137. Das ist kein Fehler im Code, sondern das Signal des Kernels: Der Prozess wurde beendet, weil ihm der Speicher ausging. Die naheliegende Reaktion — dem Runner mehr Arbeitsspeicher geben — verschiebt das Problem nur.

Nicht raten, messen

Statt am Speicherlimit zu drehen, lässt man die Laufzeit erzählen, wohin der Speicher fließt. Ein ausführliches Garbage-Collection-Log zeigt die Belegung über die Zeit: Wächst sie stetig und wird nie wieder freigegeben, ist es ein Leck; kommt sie in Sägezähnen zurück, ist es nur eine kurze Spitze.

Im konkreten Fall zeigte das Log:

  • Die Belegung stieg monoton, GC-Pausen wurden immer länger.
  • Kurz vor dem Abbruch hielt ein einziger Cache über ein Gigabyte — aufgebaut während des Builds, nie geleert.
  • Der Compiler selbst blieb genügsam. Der Verdächtige war die Build-Logik drumherum.

Die Behebung

Der Cache bekam eine Obergrenze und wurde nach jedem Schritt freigegeben. Danach blieb die Belegung flach, die GC-Pausen kurz, der Build grün — ohne dem Runner ein Byte mehr Speicher zu geben.

Die Lehre

Out-of-Memory ist eine Aussage über Belegung, nicht über den offensichtlichsten Prozess. Das Speicher-Log zeigt den wahren Verursacher; das Limit anzuheben übertönt ihn nur, bis der Datensatz eine Spur größer wird.