Skip to content

fix: prevent crash when applying Yjs update with invalid Slate path#430

Open
juliankrispel wants to merge 4 commits into
BitPhinix:mainfrom
guruhq:fix/defensive-path-handling
Open

fix: prevent crash when applying Yjs update with invalid Slate path#430
juliankrispel wants to merge 4 commits into
BitPhinix:mainfrom
guruhq:fix/defensive-path-handling

Conversation

@juliankrispel
Copy link
Copy Markdown
Contributor

@juliankrispel juliankrispel commented Feb 25, 2026

Summary

When applying a remote Yjs update to the Slate document, the code can call Node.get(editor, path) with a path that no longer exists (e.g. after paste/duplication or path skew). This causes Slate to throw "Cannot find a descendant at path", crashing the app. This is a reoccuring issue with this library unfortunately.

This PR adds defensive handling in the Yjs→Slate apply path:

  • Catch sync-skew errors (path not found, yOffset out of bounds, etc.) in applyYjsEvents
  • Re-sync the Slate editor from Yjs when an error is detected (same pattern as connect())
  • Preserve user selection via Yjs relative positions during re-sync
  • Throttle re-syncs to max once per second to avoid performance issues if errors repeat
  • Return null instead of throwing in absolutePositionToSlatePoint for cursor safety

Scope

  • Only the Yjs→Slate apply path in packages/core
  • No API changes
  • No changes to Slate→Yjs or cursor/history behaviour

Changes

  • New file: packages/core/src/utils/errors.ts - Helper to detect sync-skew errors
  • Modified: packages/core/src/applyToSlate/index.ts - Try/catch with re-sync, selection preservation, throttle guard
  • Modified: packages/core/src/utils/position.ts - Defensive handling in absolutePositionToSlatePoint

Test plan

  • All existing tests pass (54/54)
  • Build succeeds
  • Manual test: paste/duplicate content, then receive a remote update; confirm no crash and document matches remote state

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Feb 25, 2026

🦋 Changeset detected

Latest commit: 853abd4

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 3 packages
Name Type
@slate-yjs/core Patch
@slate-yjs/example-backend Patch
@slate-yjs/example Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

- Update .nvmrc from lts/gallium (Node 16 EOL) to lts/iron (Node 20 LTS)
- Upgrade actions/checkout from v2 to v4
- Upgrade actions/setup-node from v2 to v4
- Upgrade docker/login-action from v1 to v3
- Upgrade docker/metadata-action from v3 to v5
- Upgrade docker/build-push-action from v2 to v5

Node 16 reached End of Life in September 2023, causing CI failures
due to GitHub Actions cache service issues with EOL Node versions.
When applying a remote Yjs update to the Slate document, the code can
call Node.get(editor, path) with a path that no longer exists (e.g.
after paste/duplication or path skew). This causes Slate to throw
"Cannot find a descendant at path", crashing the app.

This change adds defensive handling in the Yjs→Slate apply path:

- Catch sync-skew errors (path not found, yOffset out of bounds, etc.)
- Re-sync the Slate editor from Yjs when an error is detected
- Preserve user selection via Yjs relative positions during re-sync
- Throttle re-syncs to max once per second to avoid performance issues
- Return null instead of throwing in absolutePositionToSlatePoint

Scope: Only the Yjs→Slate apply path; no API changes.
@juliankrispel juliankrispel force-pushed the fix/defensive-path-handling branch from 60ec988 to 744d1a2 Compare February 25, 2026 14:24
@phal0r
Copy link
Copy Markdown

phal0r commented Mar 6, 2026

@juliankrispel We are also using slate with yjs and see some unexpected behaviour. Do you know if smeone still maintains this library?

@BitPhinix
Copy link
Copy Markdown
Owner

Nope - not working on it anymore! Happy to make you maintainer @juliankrispel if interested

@phal0r
Copy link
Copy Markdown

phal0r commented Mar 9, 2026

I would be also interested to contribute @BitPhinix. We are using it within plate and there are some things that need improvement

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