hcengineering/platform · error

Failed to apply ydoc update

Error message

Failed to apply ydoc update

What it means

yDocFromBuffer wraps a Buffer of Yjs update data and applies it to a (possibly new) YDoc via applyUpdate. If applyUpdate throws (corrupt, truncated, or incompatible update bytes), the error is rethrown as 'Failed to apply ydoc update' with the original error attached as cause.

Source

Thrown at foundations/server/packages/collaboration/src/ydoc.ts:35

import {
  AbstractType as YAbstractType,
  Doc as YDoc,
  applyUpdate,
  encodeStateAsUpdate,
  XmlElement as YXmlElement
} from 'yjs'

export { XmlElement as YXmlElement, XmlText as YXmlText, AbstractType as YAbstractType } from 'yjs'

/** @public */
export function yDocFromBuffer (buffer: Buffer, ydoc?: YDoc): YDoc {
  ydoc ??= new YDoc({ guid: generateId(), gc: false })
  try {
    const uint8arr = new Uint8Array(buffer)
    applyUpdate(ydoc, uint8arr)
    return ydoc
  } catch (err) {
    throw new Error('Failed to apply ydoc update', { cause: err })
  }
}

/** @public */
export function yDocToBuffer (ydoc: YDoc): Buffer {
  const update = encodeStateAsUpdate(ydoc)
  return Buffer.from(update.buffer)
}

/** @public */
export function yDocCopyXmlField (ydoc: YDoc, source: string, target: string): void {
  const srcField = ydoc.getXmlFragment(source)
  const dstField = ydoc.getXmlFragment(target)

  ydoc.transact((tr) => {
    // similar to XmlFragment's clone method
    dstField.delete(0, dstField.length)
    dstField.insert(0, srcField.toArray().map((item) => (item instanceof YAbstractType ? item.clone() : item)) as any)

View on GitHub (pinned to 63e28dc964)

Solutions

  1. Inspect err.cause for the exact decode failure and verify the buffer's integrity (length, magic bytes) at the storage layer
  2. Recover the document from an earlier snapshot/backup or regenerate it from the source-of-truth data
  3. Delete/clean the corrupted collab blob so the system recreates the ydoc from a fresh state
  4. Pin compatible Yjs versions between writer and reader to avoid encoding incompatibilities

Example fix

// before
const doc = yDocFromBuffer(corruptedBuffer)
// after
let doc
try {
  doc = yDocFromBuffer(buffer)
} catch (err) {
  console.error('ydoc corrupt, recreating:', err.cause)
  doc = yDocFromBuffer(Buffer.alloc(0)) // fresh empty doc
}
Defensive patterns

Strategy: try-catch

Validate before calling

function isValidYdocBuffer(buf: Buffer): boolean {
  return Buffer.isBuffer(buf) && buf.length > 0 && buf.length < 100 * 1024 * 1024 // reject empty/huge
}

Type guard

function isNonEmptyBuffer(v: unknown): v is Buffer {
  return Buffer.isBuffer(v) && v.length > 0
}

Try / catch

try {
  const doc = yDocFromBuffer(buffer)
} catch (err) {
  console.error('Corrupt ydoc:', (err as Error & { cause?: unknown }).cause)
  // recover from snapshot/backup or recreate an empty doc
  const doc = yDocFromBuffer(Buffer.alloc(0))
}

Prevention

When it happens

Trigger: Loading a collaboration ydoc from storage where the stored buffer is corrupted, truncated, empty/garbage, or was written by an incompatible Yjs/encoding version; passing a non-update buffer to yDocFromBuffer.

Common situations: Partial writes to blob storage leaving truncated ydoc data; manually edited or migrated collaboration blobs; version skew after a Yjs library upgrade; restoring from backups with damaged data.

Related errors


AI-assisted analysis of hcengineering/platform@63e28dc964 (2026-08-29). Data as JSON: /api/errors/93a70458ad2dc8cf. Report an issue: GitHub.