ianstormtaylor/slate · error · Error
Failed to attach MutationObserver, `node` is undefined
Error message
Failed to attach MutationObserver, `node` is undefined
What it means
RestoreDOM's MutationObserver wrapper throws when observe() is called before the restored DOM node ref exists (node.current is undefined). The observer must attach to the actual DOM element rendered by the <Slate> component; if the ref is not populated yet, restoration of DOM state cannot work.
Source
Thrown at packages/slate-react/src/components/restore-dom/restore-dom.tsx:40
type RestoreDOMProps = {
children?: ReactNode
receivedUserInput: RefObject<boolean>
node: RefObject<HTMLDivElement>
}
// We have to use a class component here since we rely on `getSnapshotBeforeUpdate` which has no FC equivalent
// to run code synchronously immediately before react commits the component update to the DOM.
class RestoreDOMComponent extends Component<RestoreDOMProps> {
static contextType = EditorContext
context: ContextType<typeof EditorContext> = null
private manager: RestoreDOMManager | null = null
private mutationObserver: MutationObserver | null = null
observe() {
const { node } = this.props
if (!node.current) {
throw new Error('Failed to attach MutationObserver, `node` is undefined')
}
this.mutationObserver?.observe(node.current, MUTATION_OBSERVER_CONFIG)
}
componentDidMount() {
const { receivedUserInput } = this.props
const editor = this.context!
this.manager = createRestoreDomManager(editor, receivedUserInput)
this.mutationObserver = new MutationObserver(this.manager.registerMutations)
this.observe()
}
getSnapshotBeforeUpdate() {
const pendingMutations = this.mutationObserver?.takeRecords()
if (pendingMutations?.length) {View on GitHub (pinned to 72a37c701e)
Solutions
- Ensure the ref passed to RestoreDOM is attached to a rendered element before observe() runs (pass the same ref used by the editable component)
- Avoid consuming internal restore-dom components directly; use the shipped <Editable>/ <Slate> components
- If on a custom setup, upgrade slate-react to a matching version so internal component contracts line up
Example fix
// before
<RestoreDOM node={{ current: null }} ... />
// after
const ref = useRef<HTMLDivElement>(null)
// attach ref to the rendered editable element
<RestoreDOM node={ref} ... /> Defensive patterns
Strategy: validation
Validate before calling
useEffect(() => {
if (!node.current) return
observe()
}, [node.current]) Prevention
- Attach refs to actually rendered elements before observing
- Don't consume slate-react internal components (restore-dom) directly in app code
- Keep slate and slate-react versions in sync to avoid internal contract drift
When it happens
Trigger: Rendering <RestoreDOM> without a valid node ref (or with a ref that is null on mount); using SlateReact internals outside the editable component; SSR where refs never populate; version mismatch between slate-react internals after upgrades.
Common situations: Custom editable components that reuse restore-dom.tsx with wrong props; upgrading slate-react across versions where RestoreDOM props changed; rendering the editor into a detached/hidden container where the ref is unset when observe runs.
Related errors
- Failed to attach MutationObserver, `node` is undefined
- Unable to find a host window element for this editor
- A HyperscriptPointRef must be passed as the ref prop of a <p
- [Slate] initialValue is invalid! Expected a list of elements
- [Slate] editor is invalid! You passed: ${Scrubber.stringify(
AI-assisted analysis of ianstormtaylor/slate@72a37c701e (2026-08-27).
Data as JSON: /api/errors/0f608bbc1ae695a0.
Report an issue: GitHub.