ianstormtaylor/slate · error · Error
Failed to attach MutationObserver, `node` is undefined
Error message
Failed to attach MutationObserver, `node` is undefined
What it means
useMutationObserver (used internally by slate-react's Android input manager) attaches a MutationObserver to a ref's current node in an effect. If node.current is still undefined when the effect runs, the observer cannot be attached, so the hook throws. This typically means the ref was never attached to a rendered DOM node or the node unmounted before the effect.
Source
Thrown at packages/slate-react/src/hooks/use-mutation-observer.ts:19
import { RefObject, useEffect, useState } from 'react'
import { useIsomorphicLayoutEffect } from './use-isomorphic-layout-effect'
export function useMutationObserver(
node: RefObject<HTMLElement>,
callback: MutationCallback,
options: MutationObserverInit
) {
const [mutationObserver] = useState(() => new MutationObserver(callback))
useIsomorphicLayoutEffect(() => {
// Discard mutations caused during render phase. This works due to react calling
// useLayoutEffect synchronously after the render phase before the next tick.
mutationObserver.takeRecords()
})
useEffect(() => {
if (!node.current) {
throw new Error('Failed to attach MutationObserver, `node` is undefined')
}
mutationObserver.observe(node.current, options)
return () => mutationObserver.disconnect()
}, [mutationObserver, node, options])
}
View on GitHub (pinned to 72a37c701e)
Solutions
- Ensure the ref is attached to a DOM element that is always rendered before the effect runs (forward the ref through any wrapper components)
- If the node renders conditionally, guard the hook usage so the observer component only mounts when the node exists
- Verify you're not calling the hook during SSR — only attach after mount
Example fix
// before
const ref = useRef<HTMLDivElement>(null)
useMutationObserver(ref, callback, options) // ref.current still null
return cond && <div ref={ref} />
// after
return <div ref={ref}>{cond && <Child />}</div>
// node always mounted; observer attaches safely Defensive patterns
Strategy: validation
Validate before calling
if (node.current != null) {
useMutationObserverEffect(node, cb, options)
} Type guard
const isRefAttached = (ref) => ref.current != null
Prevention
- Always attach the ref to an unconditionally rendered DOM element
- Forward refs through wrapper components
- Never call observer hooks during SSR
When it happens
Trigger: Passing a ref object to useMutationObserver whose .current is null/undefined at effect time (node not yet mounted, component returned null, or the ref was never forwarded to a DOM element); SSR where refs never populate.
Common situations: Using useAndroidInputManager or useMutationObserver with a conditionally-rendered element; forgetting to forward the ref in a wrapped component; React 18 strict-mode timing changes on Android-focused code paths.
Related errors
- Failed to attach MutationObserver, `node` is undefined
- A HyperscriptPointRef must be passed as the ref prop of a <p
- Cannot save pointer when pointerNode is null
- Cannot restore point because saved node is no longer in save
- Cannot restore point because saved chunk is no longer connec
AI-assisted analysis of ianstormtaylor/slate@72a37c701e (2026-08-27).
Data as JSON: /api/errors/850a549fabc5073d.
Report an issue: GitHub.