{"record":{"id":"3156c54d39df4852","repo":"BookStackApp/BookStack","slug":"unexpected-delta-format","errorCode":null,"errorMessage":"Unexpected delta format","messagePattern":"Unexpected delta format","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"resources/js/wysiwyg/lexical/yjs/CollabElementNode.ts","lineNumber":224,"sourceCode":"\n          currIndex += insertDelta.length;\n        } else {\n          const sharedType = insertDelta;\n          const {nodeIndex} = getPositionFromElementAndOffset(\n            this,\n            currIndex,\n            false,\n          );\n          const collabNode = $getOrInitCollabNodeFromSharedType(\n            binding,\n            sharedType as XmlText | YMap<unknown> | XmlElement,\n            this,\n          );\n          children.splice(nodeIndex, 0, collabNode);\n          currIndex += 1;\n        }\n      } else {\n        throw new Error('Unexpected delta format');\n      }\n    }\n  }\n\n  syncChildrenFromYjs(binding: Binding): void {\n    // Now diff the children of the collab node with that of our existing Lexical node.\n    const lexicalNode = this.getNode();\n    invariant(\n      lexicalNode !== null,\n      'syncChildrenFromYjs: could not find element node',\n    );\n\n    const key = lexicalNode.__key;\n    const prevLexicalChildrenKeys = $createChildrenArray(lexicalNode, null);\n    const nextLexicalChildrenKeys: Array<NodeKey> = [];\n    const lexicalChildrenKeysLength = prevLexicalChildrenKeys.length;\n    const collabChildren = this._children;\n    const collabChildrenLength = collabChildren.length;","sourceCodeStart":206,"sourceCodeEnd":242,"githubUrl":"https://github.com/BookStackApp/BookStack/blob/18f8469a1c72f8cc8497e9372635e6dea5028071/resources/js/wysiwyg/lexical/yjs/CollabElementNode.ts#L206-L242","documentation":"CollabElementNode.applyChildrenYjsDelta applies a Yjs delta to the element's children. Each delta event must contain either a delete or an insert key; when a delta entry has neither (a delta object in an unrecognized shape), the code throws 'Unexpected delta format'. This indicates the Yjs XmlText delta does not match the formats the Lexical yjs binding understands (string insert, shared-type insert, or delete with retain).","triggerScenarios":"A Yjs update applied to a CollabElementNode's XmlText whose delta entry contains only retain (no insert/delete), or contains unsupported keys such as a format-only or custom-annotated delta, so both deleteDelta and insertDelta come back null/undefined.","commonSituations":"Yjs provider/client version mismatch producing deltas the binding wasn't written for (e.g. y-protocols/Yjs upgrade changing delta shapes); custom Yjs transforms or snapshots introducing retain-only or format deltas; corrupted or manually crafted Yjs updates fed to the CollabCompositor; mixing Lexical collab state between incompatible versions.","solutions":["Check that all clients use compatible versions of lexical, @lexical/yjs, and yjs; align dependencies across the app.","Inspect the raw delta (console.log the event in applyChildrenYjsDelta) to identify the unexpected entry and whether a custom transform or plugin produced it.","Remove or normalize custom Yjs annotations/format deltas on the shared XmlText used by Lexical.","Reset collab state: re-initialize the document from a fresh Y.Doc / snapshot rather than replaying the problematic update.","Catch the error around yjsSyncPlugin/update application and force a full re-sync (syncChildrenFromYjs) instead of crashing the editor."],"exampleFix":"// before\nprovider.on('sync', () => applyUpdates(rawUpdates));\n// after\ntry {\n  applyUpdates(rawUpdates);\n} catch (e) {\n  if (e.message === 'Unexpected delta format') {\n    // resync from authoritative doc instead of replaying bad update\n    editor.update(() => collabCompositor.syncChildrenFromYjs(binding));\n  } else {\n    throw e;\n  }\n}","handlingStrategy":"try-catch","validationCode":"function isKnownDelta(entry) {\n  return entry != null && (entry.insert !== undefined || entry.delete !== undefined);\n}\n// validate before applying: delta.every(isKnownDelta)","typeGuard":"function isSupportedDelta(d) {\n  return d != null && typeof d === 'object' &&\n    (('insert' in d) || ('delete' in d));\n}","tryCatchPattern":"try {\n  collabNode.applyChildrenYjsDelta(binding, delta);\n} catch (e) {\n  if (e.message === 'Unexpected delta format') {\n    console.error('Unrecognized Yjs delta, resyncing:', delta);\n    resyncFromAuthoritativeDoc();\n  } else throw e;\n}","preventionTips":["Keep yjs, y-protocols, and @lexical/yjs versions identical across all clients and the server.","Do not attach custom formats/annotations to the shared XmlText used by Lexical collab.","Validate or sanitize snapshots/updates before applying them to the collaborative doc.","Provide a resync path (rebuild from an authoritative Y.Doc) for corrupted updates."],"tags":["yjs","collaboration","lexical","delta-format","sync"],"backgroundTag":"unexpected-yjs-delta-format","analyzedSha":"18f8469a1c72f8cc8497e9372635e6dea5028071","analyzedAt":"2026-09-02T19:49:33.068Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}