BookStackApp/BookStack · error · Error

Unexpected delta format

Error message

Unexpected delta format

What it means

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).

Source

Thrown at resources/js/wysiwyg/lexical/yjs/CollabElementNode.ts:224

          currIndex += insertDelta.length;
        } else {
          const sharedType = insertDelta;
          const {nodeIndex} = getPositionFromElementAndOffset(
            this,
            currIndex,
            false,
          );
          const collabNode = $getOrInitCollabNodeFromSharedType(
            binding,
            sharedType as XmlText | YMap<unknown> | XmlElement,
            this,
          );
          children.splice(nodeIndex, 0, collabNode);
          currIndex += 1;
        }
      } else {
        throw new Error('Unexpected delta format');
      }
    }
  }

  syncChildrenFromYjs(binding: Binding): void {
    // Now diff the children of the collab node with that of our existing Lexical node.
    const lexicalNode = this.getNode();
    invariant(
      lexicalNode !== null,
      'syncChildrenFromYjs: could not find element node',
    );

    const key = lexicalNode.__key;
    const prevLexicalChildrenKeys = $createChildrenArray(lexicalNode, null);
    const nextLexicalChildrenKeys: Array<NodeKey> = [];
    const lexicalChildrenKeysLength = prevLexicalChildrenKeys.length;
    const collabChildren = this._children;
    const collabChildrenLength = collabChildren.length;

View on GitHub (pinned to 18f8469a1c)

Solutions

  1. Check that all clients use compatible versions of lexical, @lexical/yjs, and yjs; align dependencies across the app.
  2. Inspect the raw delta (console.log the event in applyChildrenYjsDelta) to identify the unexpected entry and whether a custom transform or plugin produced it.
  3. Remove or normalize custom Yjs annotations/format deltas on the shared XmlText used by Lexical.
  4. Reset collab state: re-initialize the document from a fresh Y.Doc / snapshot rather than replaying the problematic update.
  5. Catch the error around yjsSyncPlugin/update application and force a full re-sync (syncChildrenFromYjs) instead of crashing the editor.

Example fix

// before
provider.on('sync', () => applyUpdates(rawUpdates));
// after
try {
  applyUpdates(rawUpdates);
} catch (e) {
  if (e.message === 'Unexpected delta format') {
    // resync from authoritative doc instead of replaying bad update
    editor.update(() => collabCompositor.syncChildrenFromYjs(binding));
  } else {
    throw e;
  }
}
Defensive patterns

Strategy: try-catch

Validate before calling

function isKnownDelta(entry) {
  return entry != null && (entry.insert !== undefined || entry.delete !== undefined);
}
// validate before applying: delta.every(isKnownDelta)

Type guard

function isSupportedDelta(d) {
  return d != null && typeof d === 'object' &&
    (('insert' in d) || ('delete' in d));
}

Try / catch

try {
  collabNode.applyChildrenYjsDelta(binding, delta);
} catch (e) {
  if (e.message === 'Unexpected delta format') {
    console.error('Unrecognized Yjs delta, resyncing:', delta);
    resyncFromAuthoritativeDoc();
  } else throw e;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of BookStackApp/BookStack@18f8469a1c (2026-09-02). Data as JSON: /api/errors/3156c54d39df4852. Report an issue: GitHub.