{"record":{"id":"c91a800894ea22d8","repo":"facebook/lexical","slug":"createorupdatenodefromyelement-node-type-is-n","errorCode":null,"errorMessage":"$createOrUpdateNodeFromYElement: Node ${type} is not registered","messagePattern":"\\$createOrUpdateNodeFromYElement: Node (.+?) is not registered","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/lexical-yjs/src/SyncV2.ts","lineNumber":109,"sourceCode":"export const $createOrUpdateNodeFromYElement = (\n  el: XmlElement,\n  binding: BindingV2,\n  keysChanged: Set<string> | null,\n  childListChanged: boolean,\n  snapshot?: Snapshot,\n  prevSnapshot?: Snapshot,\n  computeYChange?: ComputeYChange,\n): LexicalNode | null => {\n  let node = binding.mapping.get(el);\n  if (node && keysChanged && keysChanged.size === 0 && !childListChanged) {\n    return node;\n  }\n\n  const type = isRootElement(el) ? RootNode.getType() : el.nodeName;\n  const registeredNodes = binding.editor._nodes;\n  const nodeInfo = registeredNodes.get(type);\n  if (nodeInfo === undefined) {\n    throw new Error(\n      `$createOrUpdateNodeFromYElement: Node ${type} is not registered`,\n    );\n  }\n\n  if (!node) {\n    node = new nodeInfo.klass();\n    keysChanged = null;\n    childListChanged = true;\n  }\n\n  if (childListChanged && node instanceof ElementNode) {\n    const children: LexicalNode[] = [];\n    const $createChildren = (childType: XmlElement | XmlText | XmlHook) => {\n      if (childType instanceof XmlElement) {\n        const n = $createOrUpdateNodeFromYElement(\n          childType,\n          binding,\n          new Set(),","sourceCodeStart":91,"sourceCodeEnd":127,"githubUrl":"https://github.com/facebook/lexical/blob/76a22dcba981b46119fcec45f935270707e26a57/packages/lexical-yjs/src/SyncV2.ts#L91-L127","documentation":"SyncV2's $createOrUpdateNodeFromYElement resolves the Y element's nodeName (or RootNode for the root) against binding.editor._nodes, the editor's registered node map. An unregistered type means the shared document contains a node type this editor doesn't know, so the binding cannot instantiate it and throws.","triggerScenarios":"A collaborating client inserted a custom node (e.g. an ImageNode or custom embed) that this editor never registered via nodes: [...]; nodeName mismatches between the serialized type string and the registered class's getType(); connecting a barebones editor to a document produced by the full playground editor.","commonSituations":"Collaborators running different app versions where one registered a new custom node; headless/SSR editors missing feature packages; copying serialized editor state between apps with different node registries; typos in node type names when registering via XML elementName mapping.","solutions":["Register the missing node class in the editor's nodes array (or extension nodes: () => [MyNode]) so its getType() matches the Y element nodeName.","Ensure all collaboration clients run versions that include the same set of custom nodes.","Check for typos/mismatches between the Y.XmlElement nodeName and the Lexical node's getType().","If the node is optional, strip or migrate unknown Y elements before syncing instead of crashing."],"exampleFix":"// before\nconst editor = createHeadlessEditor({nodes: [RootNode, TextNode] /* ... */});\n// after\nconst editor = createHeadlessEditor({\n  nodes: [...DEFAULT_NODES, ImageNode, PageBreakNode],\n});","handlingStrategy":"validation","validationCode":"editor.read(() => {\n  const missing = allDocTypes.filter(t =>\n    t !== 'root' && !editor.hasNodes([/* map t to class */]));\n  if (missing.length) throw new Error('Unregistered shared node types: ' + missing);\n});","typeGuard":"function hasRegisteredNode(editor: LexicalEditor, type: string): boolean {\n  return editor._nodes.has(type);\n}","tryCatchPattern":"try {\n  createBinding(editor, provider, root);\n} catch (e) {\n  if (e.message.includes('is not registered')) {\n    // upgrade editor config / block sync until nodes are registered\n  } else throw e;\n}","preventionTips":["Register every custom node shared over Yjs in every client's editor config","Keep collaborator app versions in sync regarding the node registry","Verify Y.XmlElement nodeName matches the Lexical node getType()","Use a feature-flagged extension exporting all shared nodes so registries can't drift"],"tags":["collaboration","yjs","unregistered-node"],"backgroundTag":"unregistered-node-type","analyzedSha":"76a22dcba981b46119fcec45f935270707e26a57","analyzedAt":"2026-08-31T21:45:54.792Z","schemaVersion":2},"datasetVersion":"2026-08-31T22:30:34.772Z"}