toeverything/AFFiNE · error · BlockSuiteError

TransformerError

TransformerError

Error message

Root block not found in doc

What it means

Transformer.docToSnapshot(doc) serializes the block tree starting from doc.root; if the doc has no root model the export cannot proceed and TransformerError is thrown. A Store without a root is one where the root block was never created, was deleted, or has not yet arrived from sync.

Solutions

  1. Guard the export: if (!doc.root) skip or return undefined.
  2. Create the root before export (in AFFiNE-like apps, call doc.load() which ensures the root structure).
  3. Wait for the doc to finish loading/syncing before triggering docToSnapshot.

Example fix

// before
const snapshot = transformer.docToSnapshot(doc);

// after
if (!doc.root) return; // nothing to export yet
const snapshot = transformer.docToSnapshot(doc);
Defensive patterns

Strategy: validation

Validate before calling

if (!doc.root) {
  console.warn(`doc ${doc.id} has no root; skipping export`);
  return undefined;
}
return transformer.docToSnapshot(doc);

Type guard

const isExportableDoc = (doc: Store): boolean => Boolean(doc.root && doc.meta);

Try / catch

try {
  snapshot = transformer.docToSnapshot(doc);
} catch (e) {
  if (e instanceof BlockSuiteError && e.message === 'Root block not found in doc') {
    return undefined; // empty/uninitialized doc: skip
  } else throw e;
}

Prevention

When it happens

Trigger: Exporting a doc that never had doc.addBlock(rootFlavour) called; exporting right after the root block was deleted; exporting before the initial sync created the root in a remote-first workflow.

Common situations: Newly created empty docs; export triggered during document load; batch export loops that iterate all docs including uninitialized ones.

Related errors


AI-assisted analysis of toeverything/AFFiNE@b4c8548c09 (2026-08-18). Data as JSON: /api/errors/34783cdf4757dfdf. Report an issue: GitHub.

Appendix: source

Thrown at blocksuite/framework/store/src/transformer/transformer.ts:109

      return snapshot;
    } catch (error) {
      console.error(`Error when transforming block to snapshot:`);
      console.error(error);
      return;
    }
  };

  docToSnapshot = (doc: Store): DocSnapshot | undefined => {
    try {
      this._slots.beforeExport.next({
        type: 'page',
        page: doc,
      });
      const rootModel = doc.root;
      const meta = this._exportDocMeta(doc);
      if (!rootModel) {
        throw new BlockSuiteError(
          ErrorCode.TransformerError,
          'Root block not found in doc'
        );
      }
      const blocks = this.blockToSnapshot(toDraftModel(rootModel));
      if (!blocks) {
        return;
      }
      const docSnapshot: DocSnapshot = {
        type: 'page',
        meta,
        blocks,
      };
      this._slots.afterExport.next({
        type: 'page',
        page: doc,
        snapshot: docSnapshot,
      });

View on GitHub (pinned to b4c8548c09)