Harden Compose Desktop crash workarounds (macOS a11y + context-menu NPE)#228
Merged
Conversation
The ComposeSceneAccessibility.defaultAccessibilityFocusTarget NPE (CMP-10170) fires in practice only on macOS, whose a11y system keeps querying AccessibleContext and so keeps driving the crashing node-sync/focus-retarget path. The existing uncaught-exception swallow only prevents process death; the a11y tree is left mid-sync and re-throws on the next focus change. Set -Dcompose.accessibility.enable=false on macOS before the first window opens (Compose reads the flag lazily when it builds the first ComposeSceneAccessibility) so the crash path never runs. An explicit -Dcompose.accessibility.enable=... on the command line is left untouched as an escape hatch. The swallow stays as the cross-platform safety net. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Pressing an arrow key while the text context menu (the right-click Copy/Paste popup) is open runs DefaultOpenContextMenu's onKeyEvent handler, which calls FocusManager.moveFocus to step between menu items; that traversal NPEs inside Compose's focus machinery, surfacing as an uncaught exception on the AWT event thread with a BasicContextMenuRepresentation frame. It is not accessibility-related and not macOS-specific, and is still unguarded in compose-multiplatform 1.11.x. Extend isKnownComposeBug to also swallow NullPointerExceptions whose stack contains a BasicContextMenuRepresentation frame, alongside the existing a11y focus-target guard. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two independent, unrecoverable upstream Compose Desktop crashes that reach production Sentry as fatal uncaught exceptions on the AWT event thread. Both are framework bugs with nothing for us to fix; the app should not die over them.
1. macOS a11y focus-target NPE (CMP-10170)
Reported on macOS (
macbookair):While retargeting a11y focus after a node is removed,
defaultAccessibilityFocusTarget()walks theAccessibletree into anArrayDeque, butgetAccessibleChild()can return null andArrayDequerejects nulls (ComposeSceneAccessibility.kt:168-169). Still unguarded in compose-multiplatform 1.11.x.We already swallow this in
installUncaughtExceptionWorkaround, but the swallow is reactive: it only prevents process death. The crash happens midsyncNodes, so the a11y tree is left inconsistent and re-throws on the next focus change. It fires in practice only on macOS, whose a11y system aggressively queriesAccessibleContext.Fix: disable the Compose Desktop accessibility bridge on macOS by setting
-Dcompose.accessibility.enable=falsebefore the first window opens (Compose reads that system property lazily when it constructs the firstComposeSceneAccessibility). With the bridge off,accessibleContextProvideris null and the crashing focus-retarget path never runs.-Dcompose.accessibility.enable=...on the command line is left untouched as an escape hatch.Trade-off: no VoiceOver support on macOS until the upstream fix lands, which beats a crash loop.
2. Context-menu arrow-key NPE
Reported separately (not macOS-specific):
Pressing an arrow key while the text context menu (right-click Copy/Paste popup) is open runs
DefaultOpenContextMenu'sonKeyEventhandler, which callsFocusManager.moveFocusto step between menu items; that traversal NPEs inside Compose's focus machinery. The crashing frame isBasicContextMenuRepresentation_skikoKt$DefaultOpenContextMenu$2$1(theFunction1<KeyEvent, Boolean>key handler). Not accessibility-related; still unguarded in 1.11.x.Fix: extend
isKnownComposeBugto also swallowNullPointerExceptions whose stack contains aBasicContextMenuRepresentationframe, alongside the existing a11y focus-target guard. (Frame-name matching is reliable because the desktop build never runs ProGuard.)Testing
./gradlew :desktopApp:ktlintCheck :desktopApp:compileKotlinpass.🤖 Generated with Claude Code