Skip to content

Fix KeyCue-triggered menu accessibility crash on macOS 26.6.2 - #55

Merged
dayglojesus merged 1 commit into
textmatelives:mainfrom
BenjaminX:fix/keycue-menu-accessibility-crash
Aug 27, 2026
Merged

Fix KeyCue-triggered menu accessibility crash on macOS 26.6.2#55
dayglojesus merged 1 commit into
textmatelives:mainfrom
BenjaminX:fix/keycue-menu-accessibility-crash

Conversation

@BenjaminX

Copy link
Copy Markdown

Summary

  • Prevent KeyCue and other accessibility clients from aborting TextMate while inspecting menus on macOS 26.6.2.
  • Preserve the existing fail-fast behavior for every other Objective-C exception.
  • Document the fix in the unreleased stability notes.

Root cause

AppKit still routes NSMenu accessibilityPerformShowMenu through the deprecated accessibilityPerformAction: API. On macOS 26.6.2 that path raises NSInvalidArgumentException because the fallback selector is no longer implemented by NSObject. The accessibility entry point catches this framework compatibility exception, but TextMate’s NSExceptionHandler delegate observes it first and calls abort().

The crash is therefore reported as SIGABRT in OakExceptionHandlerDelegate, with the originating accessibility request attributed to KeyCue.

Fix

Recognize only the exact NSInvalidArgumentException reason emitted by this NSMenu path and return without calling abort(), allowing AppKit to reach its own catch boundary. No NSMenu swizzling or broad NSInvalidArgumentException suppression is introduced.

Verification

  • Reproduced the exception with a minimal native NSMenu probe on macOS 26.6.2.
  • Linked a regression harness against the rebuilt libOakDebug.a; it exits 0 after the exception reaches the outer catch boundary. Before this change the same path aborts.
  • Built the complete Release TextMate target successfully with CMake and Ninja.
  • Verified the resulting TextMate.app code signature with codesign --verify --deep --strict.
  • git diff --check passes.

Crash signature

NSInvalidArgumentException: -[NSMenu accessibilityPerformAction:]: unrecognized selector sent to instance ...
-[OakExceptionHandlerDelegate exceptionHandler:shouldLogException:mask:]
-[NSMenu(Accessibility) accessibilityPerformAction:]
-[NSMenu accessibilityPerformShowMenu]

Allow AppKit's known NSMenu accessibility compatibility exception to reach its framework catch boundary instead of aborting TextMate.
@BenjaminX
BenjaminX requested a review from dayglojesus as a code owner August 27, 2026 07:37
@BenjaminX BenjaminX mentioned this pull request Aug 27, 2026

@dayglojesus dayglojesus left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @BenjaminX — excellent work all around: a clear crash report, a correct root-cause analysis, and a tightly scoped fix, all inside a day.

The log lines you posted on #54 confirm the guard matches the real crash exactly (-[NSMenu accessibilityPerformAction:], plain NSMenu receiver, two occurrences a minute apart), so this is verified end-to-end. The narrow match plus the existing FSExecutionErrorException precedent makes this an easy approve.

One non-blocking thought for a possible follow-up: since the reason string embeds the receiver's dynamic class, a subclass of NSMenu (e.g. TextMate's own OakMainMenu menu bar) would produce a reason the hasPrefix: check doesn't match. No evidence any AX client hits that path — your crashes both landed on plain NSMenu submenus — but loosening the match to ignore the class name would be cheap insurance if this ever resurfaces.

Merging. Thanks again for the contribution!


Generated by Claude Code

@dayglojesus
dayglojesus merged commit 8f49367 into textmatelives:main Aug 27, 2026
@dayglojesus dayglojesus mentioned this pull request Aug 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants