Skip to content

Fix composer cut crash + suppress third-party plugin Sentry noise#2755

Merged
bengotow merged 1 commit into
masterfrom
claude/awesome-ritchie-t5hipp
Jun 19, 2026
Merged

Fix composer cut crash + suppress third-party plugin Sentry noise#2755
bengotow merged 1 commit into
masterfrom
claude/awesome-ritchie-t5hipp

Conversation

@bengotow

Copy link
Copy Markdown
Collaborator

Summary

Fixes two Sentry issues found in the 1.22.0 release:

MAILSPRING-CLIENT-42 — Composer cut crashes with "Cannot read properties of undefined (reading 'firstChild')" (17 users, 41 events)

Root cause: onCut passed the real next callback to onCopy, which called next() once internally. Then onCut called next() a second time. This double-invocation caused slate-react's cloneFragment to run twice: the first time worked fine, but on the second invocation the DOM selection had already been modified by the cut, so firstChild was undefined.

slate-react:1740 (cloneFragment)  ← crashes here (second invocation)
slate-react:2357 (onCut)
slate:11430 (next)                ← second next() call, from onCut
composer-editor.tsx:221 (onCopy)  → next()  ← first next() call
slate:11430 (next)
composer-editor.tsx:225 (onCut)   → this.onCopy(event, editor, next)
slate-react:3011 (onCut)

Fix: Pass a no-op callback to onCopy from onCut, then call next() exactly once in onCut. onCopy still sets the text/html and text/plain clipboard data; the single next() call lets Slate attach its fragment and perform the text deletion.

MAILSPRING-CLIENT-3 — "Failed to activate plugin mailspring-avatars" (35 users, 475 events)

Root cause: mailspring-avatars is a user-installed third-party plugin (not in internal_packages). It fails with Cannot read properties of undefined (reading 'string') during activation — likely because it relies on a deprecated API (e.g. React.PropTypes.string). We have no control over this plugin's code.

Fix: In package-manager.ts, only report activation failures to Sentry for built-in packages (those whose directory is under resourcePath). For user-installed plugins, the error is still logged to the console but no longer sent to Sentry, where it is not actionable.

Test plan

  • Open the composer, write some text, select it, and press Ctrl+X (Cut) — text should be cut to clipboard without a crash
  • Confirm Ctrl+C (Copy) still works normally
  • Confirm paste from cut works correctly in both composer and other apps
  • Install a broken third-party plugin and confirm its activation error appears in the DevTools console but NOT in Sentry

Sentry links

🤖 Generated with Claude Code

https://claude.ai/code/session_01HgZZbFxdx38Ngc9vpanNow


Generated by Claude Code

…gins

MAILSPRING-CLIENT-42: onCut was passing the real `next` callback to
onCopy, which called next() internally. Then onCut called next() again,
invoking slate-react's cloneFragment twice. On the second invocation the
DOM selection was already modified, causing "Cannot read properties of
undefined (reading 'firstChild')". Fixed by passing a no-op to onCopy
and calling next() exactly once in onCut.

MAILSPRING-CLIENT-3: User-installed third-party plugins (e.g.
mailspring-avatars) fail to activate when they rely on deprecated or
changed APIs. These failures are not actionable for Mailspring
maintainers. Changed package-manager to only report activation errors to
Sentry for built-in (internal_packages) plugins; user-installed plugin
errors are now only logged to the console.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HgZZbFxdx38Ngc9vpanNow
@indent-staging

indent-staging Bot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor
PR Summary

Two unrelated stability fixes for the composer and the plugin loader. The composer Cut path was calling slate-react's middleware chain twice (once via onCopy's internal next() and once explicitly), causing cloneFragment to run a second time on an already-mutated DOM and crash with "Cannot read properties of undefined (reading 'firstChild')". Plugin activation failures from user-installed third-party plugins were being reported to Sentry even though they're not actionable for Mailspring maintainers.

  • ComposerEditor.onCut now passes a no-op to this.onCopy(...) and calls next() exactly once so slate-react's cloneFragment + editor.delete() runs a single time.
  • PackageManager.activatePackage only forwards activation errors to AppEnv.reportError when pkg.directory.startsWith(this.resourcePath) (built-in internal_packages); third-party plugin failures are logged via console.error only.
  • Localized error message is hoisted into a local const message to avoid duplication across the two reporting branches.

Issues

No issues found.

CI Checks

All CI checks passed on commit 09cfd4d.

Custom Rules 3 rules evaluated, 3 passed, 0 failed

Passing This is a longer title to see what happens when they are too long to fit
Passing B
Passing Ben Rule

View all rules

@bengotow bengotow merged commit a1a3573 into master Jun 19, 2026
2 checks passed
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