ianstormtaylor/slate · error · Error
Cannot set the "then" property of a node to a function
Error message
Cannot set the "then" property of a node to a function
What it means
Slate refuses to set a node's 'then' property to a function. A thenable node would be treated as a Promise-like object, breaking await behavior, React Suspense, and serialization when nodes are returned from async code.
Source
Thrown at packages/slate/src/interfaces/transforms/general.ts:266
throw new Error(`Cannot set properties on the root node!`)
}
modifyDescendant(editor, path, node => {
const newNode = { ...node }
for (const key in newProperties) {
if (NON_SETTABLE_NODE_PROPERTIES.includes(key)) {
throw new Error(`Cannot set the "${key}" property of nodes!`)
}
const value = newProperties[<keyof Node>key]
// Make sure we're not setting `then` to a function, since this will
// cause the node to be treated as a Promise-like object, which can
// cause unexpected behaviour when returning the node from async
// functions.
if (key === 'then' && typeof value === 'function') {
throw new Error(
'Cannot set the "then" property of a node to a function'
)
}
if (value == null) {
delete newNode[<keyof Node>key]
} else {
newNode[<keyof Node>key] = value
}
}
// properties that were previously defined, but are now missing, must be deleted
for (const key in properties) {
if (!Object.hasOwn(newProperties, key)) {
delete newNode[<keyof Node>key]
}
}
View on GitHub (pinned to 72a37c701e)
Solutions
- Whitelist the keys you set: only copy known-safe property keys instead of spreading whole objects into setNodes.
- Strip 'then' (and any function-valued keys) from deserialized properties before applying.
- If you genuinely need a then field, store it as a non-function value or under a different key.
Example fix
// before
Transforms.setNodes(editor, props, { at: path }) // props may contain then
// after
const safe = Object.fromEntries(
Object.entries(props).filter(
([k, v]) => k !== 'then' && typeof v !== 'function'
)
)
Transforms.setNodes(editor, safe, { at: path }) Defensive patterns
Strategy: validation
Validate before calling
const safe = Object.fromEntries(
Object.entries(props).filter(
([k, v]) => k !== 'then' && typeof v !== 'function'
)
)
Transforms.setNodes(editor, safe, { at: path }) Type guard
function hasNoThenFunction(props: Record<string, unknown>): boolean {
return !('then' in props) || typeof props.then !== 'function'
} Prevention
- Strip 'then' and function-valued keys from deserialized node properties.
- Whitelist known-safe keys when setting node props from external data.
- Never spread arbitrary objects into setNodes.
When it happens
Trigger: Applying set_node where newProperties.then is a function — typically accidental, e.g. spreading an object containing a then callback into Transforms.setNodes props, or deserializing untrusted JSON into node properties.
Common situations: Spreading arbitrary/foreign objects into node properties; accepting node JSON from untrusted input; test fixtures accidentally including a then function.
Related errors
- Cannot set properties on the root node!
- Cannot set the "${key}" property of nodes!
- Cannot set the "then" property of the selection to a functio
- Cannot resolve a Slate range from a DOM event: ${event}
- Unable to find the path for Slate node: ${Scrubber.stringify
AI-assisted analysis of ianstormtaylor/slate@72a37c701e (2026-08-27).
Data as JSON: /api/errors/b461f1d18b6931d4.
Report an issue: GitHub.