Platform
ScaiWave ScaiGrid ScaiCore ScaiBot ScaiDrive ScaiKey Models Tools & Services
Solutions
Organisations Developers Internet Service Providers Managed Service Providers AI-in-a-Box
Resources
Support Documentation Blog Downloads
Company
About Research Careers Investment Opportunities Contact
Log in

Note content out of sync

The notes editor uses a Yjs CRDT for live multi-cursor collaboration. The CRDT state is cached in Redis as a snapshot; the canonical body is Note.body in MariaDB (written by REST autosave). Divergence between the two is the cause of most "out of sync" symptoms.

Symptom: Reload shows old content#

You typed, you saw your text appear, you reload the page, and the note rolls back to an older state.

Cause: REST autosave didn't fire (or failed silently); the CRDT state had your edits but Note.body didn't. On reload, the editor reconciles to Note.body and your edits are lost.

Mitigation: the editor watches for unsaved changes and warns on navigation. If you ignored the warning, the unsaved text is gone.

Symptom: Two devices show different content#

Multiple devices editing the same note at once should sync via Yjs. If they don't:

  • Yjs WebSocket disconnected on one side. The editor shows a disconnected indicator; reconnect by reloading.
  • CRDT state diverged because one side was offline for a long time. The reconciliation favours the latest server-side Note.body on first sync; offline edits in the offline client may be lost.

Symptom: Editor shows different content than preview#

Edit and Preview both render the same source; they should never disagree. If they do:

  • Stale render cache in the preview. Switch to Edit and back.
  • Markdown bug — preview renderer mishandled something the CodeMirror editor renders fine. File a bug.

Symptom: Note suddenly has someone else's edits I didn't see#

That's how CRDT collaboration works — when two people edit a note at the same time, both their edits merge. You may see a teammate's text appear without a notification (notes don't notify on each edit; only when comments are added or todos change).

Symptom: SW_NOTE_CONFLICT on REST PUT#

A REST PUT to update a note conflicted with concurrent edits via the CRDT. The CRDT path is preferred — use the editor, or read the current state via GET, merge your changes, and PUT again.

Server-side: Yjs snapshot wipe#

If the Redis-cached Yjs snapshots are stale (e.g. after a schema migration), restart the API; on first boot a one-shot wipe runs that clears them and reconciles from Note.body. The wipe runs once per migration version (gated by a Redis flag); subsequent restarts don't.

If you suspect Yjs state is corrupt for a single note:

bash
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
.venv/bin/python -c "
import asyncio, redis.asyncio as aioredis
from app.config import Settings
async def main():
    s = Settings()
    r = aioredis.from_url(s.redis_url, decode_responses=False)
    await r.delete(b'sw:<tenant>:note_collab_snapshot:<note-id>')
    await r.aclose()
asyncio.run(main())
"

Re-open the note; it'll seed a fresh snapshot from Note.body.

What's logged#

  • notes.yjs_snapshot_wipe — first-boot wipe on migration.
  • notes.crdt_reconcile_to_server — editor seeded from Note.body.
  • notes.autosave_failed — REST autosave PUT errored.

Greppable in your log aggregator.

Updated 2026-05-17 13:10:03 View source (.md) rev 3