Affected Packages
tiptap/extension-table
Version(s)
3.13.0
Bug Description
Bug description
Pasting a table with merged cells into an existing TipTap table crashes with
an uncaught RangeError: No cell with offset found when the bottom-right
corner of the copied selection is covered by a rowspan or colspan cell
that starts in an earlier row or column.
On Windows, an additional issue causes the crash to happen even for simpler
tables (see Root cause → Issue 1 below).
Steps to reproduce
- Create a TipTap editor with
TableKit enabled and insert a table.
- In any application (Google Sheets, Excel, Word), create a table where
the last column of the selection ends inside a merged cell:
┌──────┬──────┬──────────┐
│ A │ B │ C │ ← C has rowspan=2
├──────┼──────┤ (spans │
│ D │ E │ 2 rows) │ ← selection ends here
└──────┴──────┴──────────┘
- Copy the table and paste it into the TipTap table.
Expected behavior
The table content is pasted, preserving merged cells.
Actual behavior
Uncaught RangeError: No cell with offset 495 found
at TableMap.findCell
at TableMap.rectBetween
at new CellSelection
at insertCells
at Plugin.handlePaste
The paste fails entirely on both macOS and Windows.
Root cause
Two issues combine to cause the crash:
Issue 1 — Windows clipboard HTML wrapping (Windows only)
Google Sheets and Excel on Windows wrap clipboard HTML in custom elements:
<google-sheets-html-origin>
<style>...</style>
<table>...</table>
</google-sheets-html-origin>
pastedCells(slice) expects the slice content to start with a table row.
When it receives the outer wrapper instead, it returns null, the built-in
handlePaste exits early, and the next handler crashes (Issue 2).
On macOS the same applications put a clean <table> directly in the clipboard,
so Issue 1 is skipped — but Issue 2 can still trigger depending on table structure.
Issue 2 — positionAt returns an invalid offset (all platforms)
insertCells creates a CellSelection after inserting cells:
new CellSelection(
tr.doc.resolve(tableStart + map.positionAt(top, left, table)),
tr.doc.resolve(tableStart + map.positionAt(bottom - 1, right - 1, table))
)
When (bottom-1, right-1) falls inside a cell covered by rowspan or colspan
from an earlier row/column, positionAt returns rowEnd - 1 (an end-of-row
sentinel, not a valid cell offset). TableMap.findCell then throws RangeError.
Workaround
We worked around both issues with a custom extension:
- Detect clipboard HTML with
rowspan/colspan ≥ 2 (including unquoted attributes from Windows: colspan=3).
- Extract just the
<table> element from the clipboard HTML, discarding the outer wrapper (fixes Issue 1).
- Append a temporary extra empty column to every row so that
positionAt(bottom-1, right-1) always resolves to an explicit cell (fixes Issue 2).
- Call
__insertCells with the modified slice.
- Delete the extra column afterwards with
deleteColumn.
Environment
|
|
| TipTap |
3.x |
| prosemirror-tables |
1.8.1 |
| Clipboard source |
Google Sheets / Microsoft Excel (Windows and macOS) |
| Browser |
Chrome (Chromium) |
Minimal reproducing table
<table>
<tr><td>A</td><td>B</td><td rowspan="2">C</td></tr>
<tr><td>D</td><td>E</td></tr>
</table>
Browser Used
Chrome
Code Example URL
No response
Expected Behavior
The table content is pasted, preserving merged cells.
Additional Context (Optional)
No response
Dependency Updates
Affected Packages
tiptap/extension-table
Version(s)
3.13.0
Bug Description
Bug description
Pasting a table with merged cells into an existing TipTap table crashes with
an uncaught
RangeError: No cell with offset foundwhen the bottom-rightcorner of the copied selection is covered by a
rowspanorcolspancellthat starts in an earlier row or column.
On Windows, an additional issue causes the crash to happen even for simpler
tables (see Root cause → Issue 1 below).
Steps to reproduce
TableKitenabled and insert a table.the last column of the selection ends inside a merged cell:
Expected behavior
The table content is pasted, preserving merged cells.
Actual behavior
The paste fails entirely on both macOS and Windows.
Root cause
Two issues combine to cause the crash:
Issue 1 — Windows clipboard HTML wrapping (Windows only)
Google Sheets and Excel on Windows wrap clipboard HTML in custom elements:
pastedCells(slice)expects the slice content to start with a table row.When it receives the outer wrapper instead, it returns
null, the built-inhandlePasteexits early, and the next handler crashes (Issue 2).On macOS the same applications put a clean
<table>directly in the clipboard,so Issue 1 is skipped — but Issue 2 can still trigger depending on table structure.
Issue 2 —
positionAtreturns an invalid offset (all platforms)insertCellscreates aCellSelectionafter inserting cells:When
(bottom-1, right-1)falls inside a cell covered byrowspanorcolspanfrom an earlier row/column,
positionAtreturnsrowEnd - 1(an end-of-rowsentinel, not a valid cell offset).
TableMap.findCellthen throwsRangeError.Workaround
We worked around both issues with a custom extension:
rowspan/colspan≥ 2 (including unquoted attributes from Windows:colspan=3).<table>element from the clipboard HTML, discarding the outer wrapper (fixes Issue 1).positionAt(bottom-1, right-1)always resolves to an explicit cell (fixes Issue 2).__insertCellswith the modified slice.deleteColumn.Environment
Minimal reproducing table
Browser Used
Chrome
Code Example URL
No response
Expected Behavior
The table content is pasted, preserving merged cells.
Additional Context (Optional)
No response
Dependency Updates