{"record":{"id":"34783cdf4757dfdf","repo":"toeverything/AFFiNE","slug":"transformererror-34783c","errorCode":"TransformerError","errorMessage":"Root block not found in doc","messagePattern":"Root block not found in doc","errorType":"exception","errorClass":"BlockSuiteError","httpStatus":null,"severity":"error","filePath":"blocksuite/framework/store/src/transformer/transformer.ts","lineNumber":109,"sourceCode":"\n      return snapshot;\n    } catch (error) {\n      console.error(`Error when transforming block to snapshot:`);\n      console.error(error);\n      return;\n    }\n  };\n\n  docToSnapshot = (doc: Store): DocSnapshot | undefined => {\n    try {\n      this._slots.beforeExport.next({\n        type: 'page',\n        page: doc,\n      });\n      const rootModel = doc.root;\n      const meta = this._exportDocMeta(doc);\n      if (!rootModel) {\n        throw new BlockSuiteError(\n          ErrorCode.TransformerError,\n          'Root block not found in doc'\n        );\n      }\n      const blocks = this.blockToSnapshot(toDraftModel(rootModel));\n      if (!blocks) {\n        return;\n      }\n      const docSnapshot: DocSnapshot = {\n        type: 'page',\n        meta,\n        blocks,\n      };\n      this._slots.afterExport.next({\n        type: 'page',\n        page: doc,\n        snapshot: docSnapshot,\n      });","sourceCodeStart":91,"sourceCodeEnd":127,"githubUrl":"https://github.com/toeverything/AFFiNE/blob/b4c8548c09da21b2898443559a5b846f0ccf5dd8/blocksuite/framework/store/src/transformer/transformer.ts#L91-L127","documentation":"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.","triggerScenarios":"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.","commonSituations":"Newly created empty docs; export triggered during document load; batch export loops that iterate all docs including uninitialized ones.","solutions":["Guard the export: if (!doc.root) skip or return undefined.","Create the root before export (in AFFiNE-like apps, call doc.load() which ensures the root structure).","Wait for the doc to finish loading/syncing before triggering docToSnapshot."],"exampleFix":"// before\nconst snapshot = transformer.docToSnapshot(doc);\n\n// after\nif (!doc.root) return; // nothing to export yet\nconst snapshot = transformer.docToSnapshot(doc);","handlingStrategy":"validation","validationCode":"if (!doc.root) {\n  console.warn(`doc ${doc.id} has no root; skipping export`);\n  return undefined;\n}\nreturn transformer.docToSnapshot(doc);","typeGuard":"const isExportableDoc = (doc: Store): boolean => Boolean(doc.root && doc.meta);","tryCatchPattern":"try {\n  snapshot = transformer.docToSnapshot(doc);\n} catch (e) {\n  if (e instanceof BlockSuiteError && e.message === 'Root block not found in doc') {\n    return undefined; // empty/uninitialized doc: skip\n  } else throw e;\n}","preventionTips":["Call doc.load() (which ensures the root) before exporting.","In batch export loops, filter docs by Boolean(doc.root).","Wait for doc ready/sync events before triggering exports."],"tags":["transformer","snapshot","export","root-block","blocksuite"],"backgroundTag":"missing-root-node","analyzedSha":"b4c8548c09da21b2898443559a5b846f0ccf5dd8","analyzedAt":"2026-08-18T21:16:52.546Z","contentChangedAt":"2026-08-18T21:16:52.546Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}