{"record":{"id":"e73cd2b405f071ee","repo":"toeverything/AFFiNE","slug":"no-root-node-found-in-the-tree","errorCode":null,"errorMessage":"No root node found in the tree","messagePattern":"No root node found in the tree","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"blocksuite/framework/store/src/transformer/transformer.ts","lineNumber":600,"sourceCode":"      nodeMap.set(draft.id, { draft, snapshot, children: [] });\n    });\n    const root = nodeMap.get(draftModels[0].draft.id) as DraftBlockTreeNode;\n\n    // Second pass: build the tree structure\n    draftModels.forEach(({ draft, parentId, index }) => {\n      const node = nodeMap.get(draft.id);\n      if (!node) return;\n\n      if (parentId) {\n        const parentNode = nodeMap.get(parentId);\n        if (parentNode && index !== undefined) {\n          parentNode.children[index] = node;\n        }\n      }\n    });\n\n    if (!root) {\n      throw new Error('No root node found in the tree');\n    }\n\n    return root;\n  }\n\n  private async _snapshotToBlock(\n    snapshot: BlockSnapshot,\n    doc: Store,\n    parent?: string,\n    index?: number\n  ): Promise<BlockModel | null> {\n    this._triggerBeforeImportEvent(snapshot, parent, index);\n\n    const flatSnapshots: FlatSnapshot[] = [];\n    this._flattenSnapshot(snapshot, flatSnapshots, parent, index);\n\n    const blockTree = await this._convertFlatSnapshots(flatSnapshots);\n","sourceCodeStart":582,"sourceCodeEnd":618,"githubUrl":"https://github.com/toeverything/AFFiNE/blob/b4c8548c09da21b2898443559a5b846f0ccf5dd8/blocksuite/framework/store/src/transformer/transformer.ts#L582-L618","documentation":"_rebuildBlockTree picks draftModels[0] as the root; when the flat draft list is empty, nodeMap.get(undefined) is undefined and it throws this plain Error. An empty list means the snapshot contained no convertible blocks: either snapshot.blocks was empty, or every block failed _snapshotToModel transformation — those failures are only console.error'ed ('Error when transforming snapshot to model data') and filtered out, leaving nothing to rebuild.","triggerScenarios":"Calling snapshot-to-doc with a snapshot whose blocks array is empty; importing a snapshot where every block's props transformation threw, so all drafts were dropped.","commonSituations":"Hand-built or truncated snapshot JSON; schema/prop mismatches (e.g. a required prop failing to convert) silently discarding all blocks; slices exported from empty selections.","solutions":["Check snapshot.blocks is present and non-empty before calling the import API.","Watch the console for 'Error when transforming snapshot to model data' entries — they name the real per-block failure that emptied the list.","Fix the block schema/props mismatch causing drafts to be dropped.","Reject or skip empty snapshots upstream instead of passing them to the transformer."],"exampleFix":"// before\nconst doc = await transformer.snapshotToDoc(collection, snapshot);\n\n// after\nif (!snapshot.blocks?.length) {\n  throw new Error('snapshot has no blocks to import');\n}\nconst doc = await transformer.snapshotToDoc(collection, snapshot);","handlingStrategy":"validation","validationCode":"function countBlocks(snapshot: { blocks?: { children?: unknown[] } }): number {\n  return 1 + (snapshot.blocks?.children ?? []).reduce(\n    (n, c) => n + countBlocks(c as never), 0\n  );\n}\nif (countBlocks(snapshot) === 0) {\n  throw new Error('snapshot contains no blocks');\n}\nawait transformer.snapshotToDoc(collection, snapshot);","typeGuard":"const snapshotHasBlocks = (snapshot: DocSnapshot): boolean =>\n  Boolean(snapshot.blocks);","tryCatchPattern":"try {\n  const doc = await transformer.snapshotToDoc(collection, snapshot);\n} catch (e) {\n  if (e instanceof Error && e.message === 'No root node found in the tree') {\n    // empty snapshot: check console for per-block transform errors, fix schema/props, retry\n  } else throw e;\n}","preventionTips":["Reject empty-blocks snapshots at the API boundary before invoking the transformer.","Watch for 'Error when transforming snapshot to model data' console errors — they explain why drafts were dropped.","Validate snapshot shape (blocks present, children arrays well-formed) after JSON.parse."],"tags":["transformer","snapshot","import","empty-tree","corruption"],"backgroundTag":"corrupted-snapshot","analyzedSha":"b4c8548c09da21b2898443559a5b846f0ccf5dd8","analyzedAt":"2026-08-18T21:16:52.546Z","contentChangedAt":"2026-08-18T21:16:52.546Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}