Skip to content

Markdown/structural insert in suggesting mode creates an un-acceptable tracked change #3780

Description

@zigapk

What happened?

In suggesting mode, inserting a paragraph via a markdown Document-API insert records a tracked change that can never be resolved, and which makes acceptAllTrackedChanges() fail for the entire document (it resolves nothing while this change exists).

trackChanges.list() reports it as a normal insert, but resolving it fails:

editor.doc.trackChanges.decide({ decision: 'accept', target: { kind: 'id', id } })
// => { success: false, failure: { code: 'PRECONDITION_FAILED',
//      message: 'replacement "<id>" missing inserted or deleted side.' } }

acceptAllTrackedChanges() returns false and clears nothing — a healthy tracked change in the same document is left unresolved too. (Individual by-id accept of a healthy change still works; it is the malformed change and the bulk accept-all path that are stuck.) A plain (non-markdown) text insert produces a clean, acceptable tracked change.

Markdown inserts throw a "tracked mode" capability error (Tracked mode is not supported for type: 'markdown' insert operations.), so callers apply them in changeMode: 'direct' — yet the direct apply still stamps a trackInsert mark, i.e. a direct edit leaks an unresolvable tracked change. Disabling track changes on the editor before the insert avoids the mark, which points at the direct path not honoring its own change mode.

Steps to reproduce

Manually:

  1. Open a document with documentMode: 'suggesting' and a user set.
  2. Insert a paragraph as markdown via the Document API ({ type: 'markdown', value }); tracked mode throws, so it applies in changeMode: 'direct'.
  3. editor.doc.trackChanges.list() → the markdown change appears, type: 'insert'.
  4. editor.doc.trackChanges.decide({ decision: 'accept', target: { kind: 'id', id: <that id> } })success: false,

PRECONDITION_FAILED: replacement "<id>" missing inserted or deleted side.
5. With that change present, editor.commands.acceptAllTrackedChanges()false, and trackChanges.list().total is unchanged — including any healthy sibling change.

Reproduced headless under Node/Bun — engine/converter issue, not rendering. You can use the minimal eproducible example attached as well.

superdoc-trackchanges-repro.js

SuperDoc version

1.42.0 (also via @superdoc-dev/sdk 1.18.0)

Browser

None

Additional context

Looks like the same inline-only track-model root cause as #3592 (structural edits have no tracked representation) and the silent-direct class in #3594 — but the failure here is worse: a malformed "replacement" that is permanently unresolvable and breaks Accept All, rather than a silent direct apply.

Metadata

Metadata

Assignees

No one assigned

    Labels

    stage: triageNew issue. Needs initial assessment and classificationstage: wipFix or feature being implementedtype: bugSomething is broken or not working as expected

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions