Track Changes Suggestion Data Mismatch: 10 Steps (2026)
TL;DR
track-changes-suggestion-data-mismatch is a CKEditor 5 error thrown when the suggestion markers embedded in your document HTML don’t agree with the suggestion data objects loaded from your database or backend. The most common culprit is an authorId that differs between the marker and the loaded suggestion record. To fix it, stop comparing HTML strings and start comparing marker metadata (suggestion ID, type, author ID, attributes) against your stored suggestion objects field by field.
What This Error Means
CKEditor 5’s official error codes page defines track-changes-suggestion-data-mismatch in one line: “Suggestion marker data does not match loaded suggestion data.” source
That definition is accurate but not particularly helpful when you’re staring at a console error at 11 PM. Here’s what it actually means.
CKEditor 5 Track Changes (also called suggestion mode) stores suggestion information in two separate places. When those two places describe different realities, the editor throws this error. The document content says one thing. Your database says another. CKEditor refuses to guess which one is right.
The reporter who opened GitHub issue #11508 in the official CKEditor 5 repository put it bluntly: the error and its description were not helpful for debugging, even after inspecting saved backend data. That issue was eventually labeled resolution:resolved and type:bug, but the confusion it documented is real.
This is a data-integrity error, not a visual formatting problem. Your rendered content might look perfect. The mismatch lives underneath.
The Two Pieces of Data That Must Match
Think of CKEditor 5 Track Changes as keeping two ledgers that must always agree. When they don’t, you get a track changes suggestion data mismatch.
Ledger 1: Suggestion Markers in the Document
CKEditor embeds suggestion metadata directly into the document HTML using special tags and attributes. A typical marker looks like this:
<suggestion-start name="insertion:e8ghd7:e390dk"></suggestion-start>
ice-cream
<suggestion-end name="insertion:e8ghd7:e390dk"></suggestion-end>
The marker name follows the pattern type:suggestionId:authorId. CKEditor also uses attributes like data-suggestion-start-before, data-suggestion-end-after, data-suggestion-start-after, and data-suggestion-end-before for block-level suggestions. source
These markers are the document’s record of what suggestions exist and who created them.
Ledger 2: Suggestion Records From Your Application
Separately, your integration loads suggestion data objects into CKEditor through either the Track Changes API or an adapter. A SuggestionData object includes fields like id, type, authorId, createdAt, data, attributes, hasComments, and originalSuggestionId. source
Where the Mismatch Happens
The error fires when these two ledgers contradict each other. The document marker might say “this span belongs to suggestion X by author Y,” while the loaded suggestion record says “suggestion X has type T, author Z, and attributes W.” Same suggestion ID, conflicting facts.
The most common debugging mistake is comparing only the visible HTML. You must compare the suggestion markers inside the document with the suggestion objects loaded from your database. Practitioners on Stack Overflow have confirmed this the hard way: one developer compared generated HTML with server-fetched HTML, saw no difference, and still couldn’t resolve the error until a commenter pointed out the authorId diverged between the marker and the suggestion object. source
Common Causes of Track Changes Suggestion Data Mismatch
Here are the root causes, ranked roughly by how often they trip up developers.
1. authorId Mismatch
This is the single most confirmed cause. The marker in your HTML contains one author ID, but the loaded suggestion object contains a different one. On Stack Overflow, this was the verified fix: the commenter found that authorId inside the <suggestion-start name="insertion:{suggestionId}:{authorId}"> marker didn’t match the authorId on the loaded suggestion object. The original poster confirmed it solved their problem. source
2. Incorrect originalSuggestionId Handling
When one user types inside another user’s existing suggestion, CKEditor splits the original suggestion. The new suggestion needs to preserve the original author, not blindly assign the current user. CKEditor’s documentation says it is “critical” to handle suggestionData.originalSuggestionId correctly, or suggestion data can become incorrect and lead to errors. source
If your adapter ignores originalSuggestionId, you will eventually produce a mismatch.
3. Dropped or Malformed Attributes
Suggestion attributes can hold important data like groupId or trackingSessionId. CKEditor recommends stringifying attributes to JSON before saving and parsing them when loading. The granularity documentation explicitly warns async integrations to save and load attributes with the rest of the suggestion data. source
If your database column silently converts the attributes object to "[object Object]" or drops it to null, you’ve created a mismatch.
4. HTML Sanitizer Strips Suggestion Markup
If your application runs HTML through an XSS sanitizer, CKEditor says you must leave suggestion tags and attributes in place because that markup is necessary for future editing sessions. source
Strip those tags and the document marker ledger becomes incomplete. When the editor loads, it can’t find the markers that correspond to your suggestion records.
A related problem shows up in broader web development. A practitioner on Reddit described saving CKEditor 5 output as an HTML string in a Flask app, then retrieving it only to find <p> encoded as <p>. That specific issue wasn’t about track changes, but it illustrates how easily editor content changes shape when stored and reinserted through backend templates. source
5. Loading Preview Markup as Source Data
CKEditor’s showSuggestionHighlights option produces output meant for preview. It cannot be passed back into editor.setData(). Saving and reloading that output creates invalid Track Changes state. source
6. Async Loading Race Condition
If suggestions are fetched asynchronously, CKEditor says the integration plugin should return a Promise from Plugin.init() so editor initialization waits for the data. Loading document content before suggestions arrive can create mismatched state. source
7. Adapter Partial Update Overwrites Full Records
CKEditor’s adapter updateSuggestion() receives only changed suggestion properties, not the full record. If your backend code treats that partial payload as a complete replacement, it may accidentally erase stored fields like attributes or data. source
8. Database Cleanup Deletes Referenced Records
Accepting or discarding a suggestion does not fire an adapter event because suggestions can be restored with undo. CKEditor recommends cleanup when the editor is destroyed or closed, by comparing suggestions in editor data to suggestions in the database. source
If your cleanup runs too early, you’ll remove suggestion records that the document markers still reference.
9. Custom Feature Integration
CKEditor disables commands by default in Track Changes mode unless they are explicitly prepared. Custom commands may need integration through APIs like markInsertion(), markDeletion(), markInlineFormat(), or markBlockFormat(). source
Custom plugins that create suggestions improperly can produce markers that no valid suggestion record can match.
Example: What a Mismatch Looks Like
This example is directly inspired by the Stack Overflow case where an authorId discrepancy caused the error.
Broken
The HTML marker says the suggestion belongs to user-2:
<p>
Hello
<suggestion-start name="insertion:suggestion-1:user-2"></suggestion-start>
world
<suggestion-end name="insertion:suggestion-1:user-2"></suggestion-end>
</p>
But the loaded suggestion object says it belongs to user-1:
{
id: 'suggestion-1',
type: 'insertion',
authorId: 'user-1',
createdAt: new Date(),
data: null,
attributes: {}
}
Same suggestion ID. Same type. Different author. That’s a track changes suggestion data mismatch.
Fixed
Change the suggestion object to match the marker:
{
id: 'suggestion-1',
type: 'insertion',
authorId: 'user-2',
createdAt: new Date(),
data: null,
attributes: {}
}
The visible text in both versions is identical. The difference is entirely in metadata. This is why HTML string comparison misses the problem.
How to Debug It
Follow this checklist when you encounter a track changes suggestion data mismatch error.
Step 1: Confirm the error. Look for the exact string track-changes-suggestion-data-mismatch in your console. This confirms it’s a CKEditor 5 Track Changes data-integrity error, not a general editor issue.
Step 2: Capture both sides of the state. When saving, log both pieces:
const editorData = editor.data.get();
const suggestionsData = trackChanges.getSuggestions({
skipNotAttached: true,
toJSON: true
});
CKEditor’s integration guide shows this exact pattern. source
Step 3: Check authorId first. This is the highest-value first check because it’s the most commonly confirmed fix. Extract the author ID from each <suggestion-start> marker name and compare it to the authorId field on the corresponding suggestion object.
Step 4: Compare all marker fields to suggestion records. For every marker in the HTML, verify:
- Marker suggestion ID matches
suggestionData.id - Marker type matches
suggestionData.type - Marker author ID matches
suggestionData.authorId - Attribute subtype or formatting data matches
suggestionData.data - Required attributes like
groupIdortrackingSessionIdmatchsuggestionData.attributes
Step 5: Test the split-suggestion scenario. Reproduce this flow: User A creates an insertion suggestion. User B types inside it. CKEditor splits the original suggestion. Verify the new suggestion preserves User A’s author through originalSuggestionId.
Step 6: Verify attributes serialization. Check that attributes round-trips correctly. It should not become "[object Object]", null, {} (when it previously had data), or a string that never gets parsed back.
Step 7: Audit your HTML sanitizer. If your app sanitizes HTML, confirm that <suggestion-start>, <suggestion-end>, and all data-suggestion-* attributes are whitelisted.
Step 8: Check for preview data contamination. Make sure you’re not saving output from editor.getData({ showSuggestionHighlights: true }) and reloading it as source data.
Step 9: Verify async loading order. If suggestions load asynchronously, confirm your plugin returns a Promise from Plugin.init() so the editor waits before processing content.
Step 10: Validate adapter methods. If using the adapter integration, verify getSuggestion(id) returns complete data, addSuggestion() saves all fields, and updateSuggestion() treats its payload as a partial update, not a full replacement.
How to Prevent It
Fixing the immediate error is only half the job. Prevention means designing your persistence layer so a track changes suggestion data mismatch can’t happen in the first place.
Save Editor Content and Suggestions Together
Treat document HTML and suggestion records as one atomic unit. A recommended schema:
{
"documentId": "doc-123",
"editorData": "<p>...</p>",
"suggestions": [
{
"id": "suggestion-1",
"type": "insertion",
"authorId": "user-2",
"createdAt": "2026-05-03T00:00:00.000Z",
"data": null,
"attributes": {}
}
],
"updatedAt": "2026-05-03T00:00:00.000Z"
}
This keeps both ledgers versioned together, which eliminates drift between document state and suggestion state.
Set Authors Server-Side
CKEditor’s adapter API says addSuggestion() should not rely on client-provided authorId. Set the author server-side for security. Use originalSuggestionId to preserve the correct author when suggestions split. source
Use the Adapter Integration for Serious Applications
CKEditor recommends adapter integration because it gives better control over data, including permissions validation, data validation, and server-side fields like creation dates. source
Ad hoc save/load patterns work for prototypes. For production systems handling collaborative editing, the adapter provides guardrails that prevent many mismatch scenarios.
Preserve Suggestion Markup During Sanitization
Whitelist all CKEditor suggestion tags and data-suggestion-* attributes in your sanitizer configuration. These aren’t decorative. They’re structural.
Add Backend Validation
Before writing to the database, verify:
- Every marker suggestion ID in
editorDatahas a matching suggestion record. - Every suggestion record referenced by the document has matching
typeandauthorId. attributesis valid JSON that round-trips as an object.- Suggestion IDs are immutable.
Clean Up at the Right Time
Don’t purge suggestion records when suggestions are accepted or discarded. CKEditor says those actions don’t fire adapter events because suggestions can be undone. Run cleanup when the editor is destroyed or closed, comparing what’s in the document to what’s in the database.
Watch for Upgrade-Related Changes
Practitioners in the Drupal community have reported that CKEditor version bumps can break integrations, including changes to markup behavior and plugin APIs. source If the mismatch appears after an upgrade, diff the saved suggestion schema and marker format before and after the version change.
The Bigger Picture: Track Changes as a State Synchronization Problem
This error isn’t unique to CKEditor in spirit, even though the exact error code is CKEditor 5-specific. In a ProseMirror community discussion, developers distinguished between tracking every historical change and Word-style suggestion workflows, noting that tracked changes cover block creation, inline additions, format changes, and block type changes. source Suggestions are structured editing objects, not just colored spans.
A Hacker News discussion of CKEditor 5 included a practitioner observation that data in input-related events can fail to correspond to the DOM changes they caused. source This reinforces the core lesson: trust CKEditor’s data APIs and internal model. Don’t manually derive Track Changes state from DOM events or raw HTML inspection.
Developers building rich text editors from scratch on Reddit have discussed how difficult it is to maintain a separate immutable document model rather than treating the DOM as the source of truth. source The track changes suggestion data mismatch error is one specific consequence of that general challenge. Any collaborative editing system that keeps suggestion metadata separate from document content faces the same alignment problem.
For teams building collaborative review workflows with editors like TinyMCE, Froala, or CKEditor 4, Track Changes plugins can handle much of this metadata synchronization complexity out of the box, rather than requiring custom persistence logic.
Comparison: CKEditor 5 Track Changes vs. Plugin-Based Approaches
The track-changes-suggestion-data-mismatch error surfaces specifically in CKEditor 5’s built-in collaboration framework, where your application is responsible for the adapter, the database, and the suggestion lifecycle.
Plugin-based approaches to track changes in editors like TinyMCE or Froala take a different architectural approach. The plugin manages its own internal state, which can simplify the integration burden for teams that don’t need CKEditor 5’s full real-time collaboration stack.
The right choice depends on your requirements. If you’re evaluating options, Loop Index’s pricing page breaks down costs for Track Changes and Inline Comments across supported editors.
FAQ
What does track-changes-suggestion-data-mismatch mean?
It means CKEditor 5 found that suggestion marker data embedded in the document does not match the suggestion data loaded from your application or database. CKEditor’s official definition is: “Suggestion marker data does not match loaded suggestion data.” source
Is this error caused by different HTML?
Not necessarily. The visible HTML may look identical. The mismatch is typically between hidden marker metadata (suggestion ID, type, or author ID encoded in the marker name) and the loaded suggestion object’s fields. In the most referenced Stack Overflow case, the issue was an authorId discrepancy that wasn’t visible in a simple HTML diff.
Which field should I check first?
Check authorId. It’s the most commonly confirmed cause. Extract the author ID from the <suggestion-start name="type:suggestionId:authorId"> marker and compare it to suggestionData.authorId.
Why does originalSuggestionId matter?
When CKEditor splits a suggestion (because a second user types inside the first user’s suggestion), the new suggestion must preserve the original author. originalSuggestionId tells your adapter which suggestion to look up for the correct author. Ignoring it leads to mismatched authorship and eventually a track changes suggestion data mismatch error.
Can HTML sanitization cause this error?
Yes. If your sanitizer strips <suggestion-start>, <suggestion-end>, or data-suggestion-* attributes, the document loses its marker ledger. When the editor loads and finds suggestion records but no corresponding markers (or vice versa), the data doesn’t align.
Should I save the output from showSuggestionHighlights?
No. CKEditor says output generated with showSuggestionHighlights is for preview purposes only and cannot be used as input for editor.setData(). source
Does this error apply to editors other than CKEditor 5?
The exact error code track-changes-suggestion-data-mismatch is CKEditor 5-specific. But the underlying problem, keeping track-change markup and suggestion metadata in sync, applies to any collaborative editing system. Any editor that stores suggestions in two places faces the same alignment challenge.
How do I prevent this error in production?
Save editor HTML and suggestion records as one versioned document state. Serialize attributes as JSON. Set authorId server-side. Handle originalSuggestionId for split suggestions. Whitelist all suggestion markup in your sanitizer. Use the adapter integration for server-side validation. Run suggestion cleanup only when the editor is destroyed, not on individual accept or discard actions.
Building collaborative review workflows means keeping document markup, authors, comments, and suggestions perfectly synchronized. If you’d rather focus on your application than on metadata plumbing, Loop Index provides Track Changes and Inline Comments plugins for TinyMCE, Froala, and CKEditor 4. Get in touch to discuss which approach fits your integration.