Skip to content

fix(summary): prevent BlockNote rendering crashes with patch + boundary#470

Open
passabilities wants to merge 3 commits into
Zackriya-Solutions:devtestfrom
passabilities:fix/summary-render-safety
Open

fix(summary): prevent BlockNote rendering crashes with patch + boundary#470
passabilities wants to merge 3 commits into
Zackriya-Solutions:devtestfrom
passabilities:fix/summary-render-safety

Conversation

@passabilities
Copy link
Copy Markdown

Description

The summary editor crashes for some meetings with a Cannot read properties of undefined (reading 'localsInner') or dom is undefined error originating in prosemirror-view, taking down the entire meeting page. This PR adds three independent layers of defense:

  1. Patch prosemirror-view to honor {dom, contentDOM} toDOM specs. BlockNote 0.36's node specs sometimes return a {dom, contentDOM} shape from toDOM, but upstream prosemirror-view unconditionally forwards the result to DOMSerializer.renderSpec, which throws when given that shape. The patch checks for the shape and uses it directly when present.

  2. Disable BlockNote's placeholder plugin. BlockNote 0.36's placeholder plugin produces a DecorationSource that's missing localsInner, which crashes DecorationGroup.locals() in prosemirror-view during the initial editor mount. We have no UX dependency on the placeholder, so disabling it is the cleanest fix.

  3. Wrap the editor in SummaryErrorBoundary. Even with (1) and (2), any future regression in the editor stack would otherwise take down the whole page. The boundary catches render failures and shows a fallback with the raw markdown plus a retry button, so a single bad summary can't break navigation.

Files

  • frontend/patches/prosemirror-view@1.41.8.patch — new pnpm patch (also patches dist/index.cjs and dist/index.js)
  • frontend/pnpm-workspace.yaml — registers the patch via patchedDependencies
  • frontend/src/components/AISummary/BlockNoteSummaryView.tsxdisableExtensions: ['placeholder'] and wraps both render paths in the boundary
  • frontend/src/components/AISummary/SummaryErrorBoundary.tsx — new class component with fallback UI

Type of Change

  • Bug fix
  • New feature
  • Documentation update
  • Performance improvement
  • Code refactoring

Testing

  • Manual testing performed — opened previously-crashing meetings and verified the editor renders; intentionally threw inside Editor to confirm the boundary catches and the rest of the UI stays interactive.
  • Unit tests added — N/A (boundary is exercised through manual fault injection; patch is a third-party dependency hot-fix).

Checklist

  • Code follows project style
  • Self-reviewed the code
  • Added comments for the non-obvious parts (placeholder disable + patch rationale)
  • No documentation needed

The summary view occasionally hits render-phase failures (e.g. BlockNote
choking on otherwise-valid block input). Without a boundary, any such
failure takes down the entire meeting page with Next.js's generic
"Application error: a client-side exception has occurred" overlay.

Add a class-based error boundary that:
- catches render-phase errors via `getDerivedStateFromError` /
  `componentDidCatch`,
- shows the raw markdown in a readable fallback so the user retains
  access to the summary content,
- exposes an optional 'Regenerate' button wired through to
  `onRegenerateSummary`.

The boundary is consumed by `BlockNoteSummaryView` in the next commit.
… specs

prosemirror-view 1.41 unconditionally pipes the result of
`node.type.spec.toDOM(node)` (and the mark equivalent) through
`DOMSerializer.renderSpec` inside `NodeViewDesc.create` /
`MarkViewDesc.create`. `renderSpec` only knows how to handle:
  - text DOM nodes,
  - `{dom: <textNode>}` objects, and
  - array specs `["tag", attrs?, ...children]`.

It does NOT handle `{dom: <element>, contentDOM?}`, which is one of
the documented valid `DOMOutputSpec` shapes — and the one BlockNote's
`renderHTML` returns for every block (via `createDefaultBlockDOMOutputSpec`
and similar helpers). The result is `RangeError: Invalid array passed
to renderSpec` thrown on every BlockNote editor mount, taking down
the whole meeting page.

Patch `prosemirror-view`'s `dist/index.js` and `dist/index.cjs` via
pnpm patch: before calling `renderSpec`, check whether the toDOM
result already has a `.dom` property and, if so, use it directly.
This preserves the array-spec path unchanged.

Register the patch in `pnpm-workspace.yaml` under `patchedDependencies`
so subsequent `pnpm install` runs apply it automatically.
…oundary

Two small touches to `BlockNoteSummaryView`:

1. Disable the `placeholder` extension on the BlockNote editor. With
   the plugin enabled, BlockNote 0.36 produces a `DecorationSource`
   that's missing the `localsInner` method ProseMirror 1.41 calls in
   `DecorationGroup.locals()` — the editor crashes on every mount with
   `TypeError: undefined is not an object (evaluating
   'this.members[i].localsInner')`. Bisected against the disable list;
   `placeholder` is the sole culprit. Other plugins (sideMenu,
   suggestionMenus, formattingToolbar, linkToolbar, filePanel,
   tableHandles, animations, etc.) work fine.

2. Wrap both render branches (`blocknote` for saved `summary_json`,
   `markdown` for fresh LLM output) in `SummaryErrorBoundary` so any
   future render-phase failure falls back to readable raw markdown
   instead of crashing the page.
@sujithatzackriya
Copy link
Copy Markdown
Collaborator

@safvanatzack please address

@safvanatzack
Copy link
Copy Markdown
Collaborator

@passabilities Thanks for the contribution

I think the ProseMirror patch/placeholder workaround here is mostly superseded by #472, which pins the BlockNote ProseMirror stack and aliases ProseMirror packages to single instances.

The useful follow-up from this PR may be the SummaryErrorBoundary, but I’d keep that separate from the dependency/runtime fix.

Thank you

bobby-claw pushed a commit to NERV-es/meetily that referenced this pull request Jun 1, 2026
…ackriya-Solutions#457 Zackriya-Solutions#430 Zackriya-Solutions#470 Zackriya-Solutions#420

Ported from upstream Zackriya-Solutions/meetily:
- Zackriya-Solutions#475: Whisper vocabulary hints (meeting domain support)
- Zackriya-Solutions#478: Export transcripts as TXT/VTT with file-save dialog
- Zackriya-Solutions#457: Integration API via deep-link URL scheme + distributed notifications
- Zackriya-Solutions#430: Apple Speech engine (cfg-gated behind 'apple-speech' feature)
- Zackriya-Solutions#470: BlockNote v0.16 editor upgrade
- Zackriya-Solutions#420: Monochrome tray icon (proper macOS template image)

Apple Speech engine gated behind feature flag due to upstream
Send/Sync issues with objc2 types — enable with:
  cargo build --features apple-speech
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.

3 participants