Symptom
Bursts of uncaught NullPointerException: Argument 'code' must not be null on the FX thread (org.kordamp.ikonli.javafx.FontIcon.setIconCode), each spawning a modal error dialog, dozens at a time (observed 2026-07-24 in a fast-dev komet-desktop session).
Diagnosis — four factors chained
- Trigger: CSSFX hot-swap. In dev mode
CssUtils loads CSS from the source tree and starts CSSFX. Editing komet.css on disk while the app runs makes CSSFXMonitor$URIStyleUpdater swap the stylesheet URI → the scene's stylesheet list changes → full-tree reapplyCSS.
- JavaFX 27-ea reset.
CssStyleHelper.createStyleHelper → resetToInitialValues resets every previously-CSS-styled styleable property to its initial value before the new stylesheet applies. This is the aggressive-reset behaviour of the CSS fix the komet-bom JavaFX pin (27-ea+24, JDK-8268657 — the CSS-corruption fix) deliberately retains; upstream backed it out in 27-ea+25, plausibly for this regression class.
- Ikonli rejects its own initial value.
FontIcon's iconCode styleable has initial value null, but its invalidation listener calls setIconCode(n) which does requireNonNull — so the reset always throws. Unfixed upstream: ikonli master (and 12.4.0, latest) still has the unguarded listener. A styleable property that cannot accept its own CssMetaData initial value is an Ikonli spec violation worth reporting upstream.
- Amplification: the alert loop.
komet.css alone carries ~94 -fx-icon-code rules — one NPE per styled icon per swap — and AlertDialogSubscriber.drainQueue shows a modal showAndWait dialog per exception; each dialog's nested event loop lets the queued CSSFX updates keep firing, so one stylesheet edit becomes a dialog storm.
Options
- Throttle/dedupe
AlertDialogSubscriber — collapse repeated identical exceptions into one dialog (or log-only after N). Bounded, uncontroversial, fixes the storm whatever the source. Recommended now.
- Upstream Ikonli fix — guard the listener (
if (n != null)) or accept null as "clear icon"; file/PR against kordamp/ikonli. The real root fix.
- CSSFX scoping — stop live-monitoring stylesheets that style FontIcons; costs the live-CSS loop dev workflow.
- Move the JavaFX ea pin — losing JDK-8268657 brings the CSS corruption back; not worth it.
Until one of these lands: expect a dialog burst whenever komet.css (or any watched stylesheet) is edited while a fast-dev app is running — including edits arriving via Syncthing from the other machine.
Symptom
Bursts of uncaught
NullPointerException: Argument 'code' must not be nullon the FX thread (org.kordamp.ikonli.javafx.FontIcon.setIconCode), each spawning a modal error dialog, dozens at a time (observed 2026-07-24 in a fast-dev komet-desktop session).Diagnosis — four factors chained
CssUtilsloads CSS from the source tree and starts CSSFX. Editingkomet.csson disk while the app runs makesCSSFXMonitor$URIStyleUpdaterswap the stylesheet URI → the scene's stylesheet list changes → full-treereapplyCSS.CssStyleHelper.createStyleHelper → resetToInitialValuesresets every previously-CSS-styled styleable property to its initial value before the new stylesheet applies. This is the aggressive-reset behaviour of the CSS fix the komet-bom JavaFX pin (27-ea+24, JDK-8268657 — the CSS-corruption fix) deliberately retains; upstream backed it out in 27-ea+25, plausibly for this regression class.FontIcon'siconCodestyleable has initial valuenull, but its invalidation listener callssetIconCode(n)which doesrequireNonNull— so the reset always throws. Unfixed upstream: ikonli master (and 12.4.0, latest) still has the unguarded listener. A styleable property that cannot accept its ownCssMetaDatainitial value is an Ikonli spec violation worth reporting upstream.komet.cssalone carries ~94-fx-icon-coderules — one NPE per styled icon per swap — andAlertDialogSubscriber.drainQueueshows a modalshowAndWaitdialog per exception; each dialog's nested event loop lets the queued CSSFX updates keep firing, so one stylesheet edit becomes a dialog storm.Options
AlertDialogSubscriber— collapse repeated identical exceptions into one dialog (or log-only after N). Bounded, uncontroversial, fixes the storm whatever the source. Recommended now.if (n != null)) or accept null as "clear icon"; file/PR against kordamp/ikonli. The real root fix.Until one of these lands: expect a dialog burst whenever
komet.css(or any watched stylesheet) is edited while a fast-dev app is running — including edits arriving via Syncthing from the other machine.