{"record":{"id":"d2b702cc47f815c2","repo":"facebook/lexical","slug":"node-name-mismatch","errorCode":null,"errorMessage":"node name mismatch!","messagePattern":"node name mismatch!","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/lexical-yjs/src/SyncV2.ts","lineNumber":1003,"sourceCode":"  for (const [stateConfig, v] of known) {\n    attrs[stateKeyToAttrKey(stateConfig.key)] = stateConfig.unparse(v);\n  }\n  return attrs;\n};\n\nexport const $updateYFragment = (\n  y: YDoc,\n  yDomFragment: XmlElement,\n  node: LexicalNode,\n  binding: BindingV2,\n  dirtyElements: Set<NodeKey>,\n) => {\n  if (\n    yDomFragment instanceof XmlElement &&\n    yDomFragment.nodeName !== node.getType() &&\n    !(isRootElement(yDomFragment) && node.getType() === RootNode.getType())\n  ) {\n    throw new Error('node name mismatch!');\n  }\n  binding.mapping.set(yDomFragment, node);\n  // update attributes\n  if (yDomFragment instanceof XmlElement) {\n    const yDomAttrs = yDomFragment.getAttributes();\n    const lexicalAttrs = {\n      ...propertiesToAttributes(node, binding),\n      ...stateToAttributes(node),\n    };\n    for (const key in lexicalAttrs) {\n      if (lexicalAttrs[key] != null) {\n        const isEqual =\n          yDomAttrs[key] === lexicalAttrs[key] ||\n          // deep equality check so we don't sync properties/state with object values every update\n          (isObject(yDomAttrs[key]) &&\n            isObject(lexicalAttrs[key]) &&\n            equalAttrs(yDomAttrs[key], lexicalAttrs[key]));\n        if (!isEqual && key !== 'ychange') {","sourceCodeStart":985,"sourceCodeEnd":1021,"githubUrl":"https://github.com/facebook/lexical/blob/76a22dcba981b46119fcec45f935270707e26a57/packages/lexical-yjs/src/SyncV2.ts#L985-L1021","documentation":"When mapping a Yjs XmlElement back to a Lexical node, SyncV2 checks that the Yjs element's nodeName equals the Lexical node's getType() (allowing the root special case). A mismatch means the shared document's structure disagrees with the Lexical node it is being bound to, which would corrupt the mapping, so it throws.","triggerScenarios":"$bindNodeToYjs (the binding function around line 1003) receives a yDomFragment that is an XmlElement whose nodeName differs from node.getType() and is not the root element mapped to RootNode.","commonSituations":"Two clients with different node schemas collaborating: one writes <heading> where the other expects 'paragraph'; custom nodes renamed via getType() after documents were created; manually constructing Yjs XML with names that don't match Lexical types.","solutions":["Align node getType() strings with the Yjs element names present in the shared document.","Migrate the Yjs document's element names if the Lexical type was renamed.","Ensure all collaborators use identical node definitions/versions (lock package versions across clients).","Verify you are passing the matching Lexical node for each XmlElement rather than an arbitrary node."],"exampleFix":"// before\nclass H1Node { getType() { return 'h1'; } } // Yjs doc has nodeName 'heading'\n// after\nclass H1Node { getType() { return 'heading'; } } // matches Yjs nodeName","handlingStrategy":"validation","validationCode":"if (yDomFragment instanceof XmlElement &&\n    yDomFragment.nodeName !== node.getType() &&\n    !(isRootElement(yDomFragment) && node.getType() === RootNode.getType())) {\n  throw new Error(`Schema mismatch: yjs=${yDomFragment.nodeName} lexical=${node.getType()}`);\n}","typeGuard":"function yjsNameMatches(yEl: unknown, node: LexicalNode): boolean {\n  return yEl instanceof XmlElement && yEl.nodeName === node.getType();\n}","tryCatchPattern":"try {\n  bindNode(binding, yDomFragment, node);\n} catch (e) {\n  if (e instanceof Error && e.message === 'node name mismatch!') {\n    console.error('Yjs/Lexical schema mismatch', {\n      yjs: (yDomFragment as XmlElement).nodeName,\n    });\n  } else { throw e; }\n}","preventionTips":["Keep getType() strings stable; treat renames as document migrations.","Use identical node definitions and versions across collaborators.","Validate Yjs document names against the Lexical schema at sync start."],"tags":["yjs","collaboration","schema-mismatch","node-type"],"backgroundTag":"dom-schema-mismatch","analyzedSha":"76a22dcba981b46119fcec45f935270707e26a57","analyzedAt":"2026-08-31T21:45:54.792Z","schemaVersion":2},"datasetVersion":"2026-08-31T22:30:34.772Z"}