gatsbyjs/gatsby · error · Error
Nodes can only be updated by their owner. Node "${node.id}"
Error message
Nodes can only be updated by their owner. Node "${node.id}" is owned by "${oldNode.internal.owner}" and another plugin "${owner}" tried to update it. What it means
When createNode is called for an id that already exists (oldNode present), the type-owners reducer checks that the new node's internal.owner matches the existing node's internal.owner. If they differ it throws, because a node id is an identity contract and allowing a second plugin to 'recreate' (overwrite) a node owned by another plugin would silently hijack data. This complements per-type ownership with per-node ownership continuity.
Source
Thrown at packages/gatsby/src/redux/reducers/type-owners.ts:115
The plugin deleting the node:
${JSON.stringify(plugin, null, 4)}
`)
}
}
return typeOwners
}
case `CREATE_NODE`: {
const { plugin, oldNode, payload: node } = action
const { owner, type } = node.internal
setTypeOwner(type, plugin, typeOwners, node)
// If the node has been created in the past, check that
// the current plugin is the same as the previous.
if (oldNode && oldNode.internal.owner !== owner) {
throw new Error(
stripIndent`
Nodes can only be updated by their owner. Node "${node.id}" is
owned by "${oldNode.internal.owner}" and another plugin "${owner}"
tried to update it.
`
)
}
return typeOwners
}
default:
return typeOwners
}
}
View on GitHub (pinned to 8b06340921)
Solutions
- Namespace your node ids so they cannot collide with other plugins (e.g. `source-x:${rawId}`).
- Clear .cache after changing which plugin owns a type so stale oldNode entries are gone.
- Ensure the same plugin consistently creates the same node id across builds.
Example fix
// before
createNode({ id: raw.slug, internal: { type: `Post`, ... } }) // collides across plugins
// after
createNode({ id: `my-source-${raw.slug}`, internal: { type: `Post`, ... } }) Defensive patterns
Strategy: validation
Validate before calling
// Namespace node ids so they cannot collide across plugins.
function namespacedId(pluginName, rawId) {
return `${pluginName}::${rawId}`
}
// createNode({ id: namespacedId('my-source', raw.id), ... }) Type guard
function isStableNamespacedId(id, pluginName) {
return typeof id === 'string' && id.startsWith(`${pluginName}::`)
} Prevention
- Derive ids from a plugin prefix + content digest.
- Run gatsby clean after changing which plugin owns a type.
- Keep id-generation deterministic across builds.
When it happens
Trigger: Plugin B calls createNode with an id that already exists in state and was created by plugin A (oldNode.internal.owner !== B's owner). Reached when two plugins generate colliding ids, or the same id is reused by different plugins across rebuilds.
Common situations: ID collision: two plugins generating the same id prefix/scheme (e.g. both using `path-1`); switching the plugin that owns a node type without clearing cache; a plugin change that altered internal.owner derivation while old nodes still persist.
Related errors
- The plugin "${ownerName}" created a node of a type owned by
- The plugin "${pluginName}" deleted a node of a type owned by
- Plugins creating nodes can not set data on the reserved fiel
- A plugin tried to update a node field that it doesn't own:
- generateImageSource must be a function
AI-assisted analysis of gatsbyjs/gatsby@8b06340921 (2026-08-13).
Data as JSON: /api/errors/94afa36b81d3ed42.
Report an issue: GitHub.