gatsbyjs/gatsby · error · Error

The plugin "${ownerName}" created a node of a type owned by

Error message

The plugin "${ownerName}" created a node of a type owned by another plugin.

The node type "${typeName}" is owned by "${existingTypeOwnerNameByTypeName}".

If you copy and pasted code from elsewhere, you'll need to pick a new type name
for your new node(s).

${fullNode ? stripIndent(`The node object passed to "createNode":

              ${JSON.stringify(fullNode, null, 4)}\n`) : ``}
The plugin creating the node:

${JSON.stringify(plugin, null, 4)}

What it means

Gatsby enforces that each node internal.type is owned by exactly one plugin. setTypeOwner records the first plugin to create a given type in typeOwners.typesToPlugins and throws if a different plugin later tries to createNode a node of that same type. This prevents two source plugins from emitting overlapping GraphQL types, which would corrupt the schema. The error names both plugins, the contested type, and (if available) dumps the offending node and plugin objects.

Source

Thrown at packages/gatsby/src/redux/reducers/type-owners.ts:37

    reportOnce(`No plugin owner for type "${typeName}"`)
    return typeOwners
  }

  const existingOwnerTypes = typeOwners.pluginsToTypes.get(ownerName)

  if (!existingOwnerTypes) {
    typeOwners.pluginsToTypes.set(ownerName, new Set([typeName]))
  } else {
    existingOwnerTypes.add(typeName)
  }

  const existingTypeOwnerNameByTypeName =
    typeOwners.typesToPlugins.get(typeName)

  if (!existingTypeOwnerNameByTypeName) {
    typeOwners.typesToPlugins.set(typeName, ownerName)
  } else if (existingTypeOwnerNameByTypeName !== ownerName) {
    throw new Error(stripIndent`
      The plugin "${ownerName}" created a node of a type owned by another plugin.

      The node type "${typeName}" is owned by "${existingTypeOwnerNameByTypeName}".

      If you copy and pasted code from elsewhere, you'll need to pick a new type name
      for your new node(s).

      ${
        fullNode
          ? stripIndent(
              `The node object passed to "createNode":

              ${JSON.stringify(fullNode, null, 4)}\n`
            )
          : ``
      }
      The plugin creating the node:

View on GitHub (pinned to 8b06340921)

Solutions

  1. Pick a unique type name for your plugin (e.g. prefix it: 'MySourcePost' instead of 'Post').
  2. If you forked a plugin, rename all internal.type values it emits.
  3. Uninstall/disable the duplicate source plugin so only one owns the type.
  4. If you are composing plugins, have one delegate node creation to the owner rather than both creating.

Example fix

// before - forked plugin reuses type
createNode({ id, internal: { type: `MarkdownRemark`, ... } })
// after
createNode({ id, internal: { type: `MyBlogMarkdownRemark`, ... } })
Defensive patterns

Strategy: validation

Validate before calling

// Verify type ownership before createNode to fail with a clearer message.
const usedTypes = new Map() // typeName -> pluginName
function claimType(typeName, pluginName) {
  const prev = usedTypes.get(typeName)
  if (prev && prev !== pluginName) {
    throw new Error(`Type '${typeName}' already owned by '${prev}'`)
  }
  usedTypes.set(typeName, pluginName)
}

Type guard

function isUniqueNodeType(typeName, pluginName, registry) {
  const prev = registry.get(typeName)
  return !prev || prev === pluginName
}

Prevention

When it happens

Trigger: Plugin B calls createNode with a node whose node.internal.type equals a type name already recorded for plugin A (A !== B). The check runs on every CREATE_NODE in the type-owners reducer.

Common situations: Copy-pasting a source plugin to make a variant but keeping the same node.internal.type (e.g. 'MarkdownRemark' or 'SourceX'); installing two source plugins that both claim a generic type like 'File' or a CMS type; a forked plugin reusing the original's type names.

Related errors


AI-assisted analysis of gatsbyjs/gatsby@8b06340921 (2026-08-13). Data as JSON: /api/errors/fc8754667532be1b. Report an issue: GitHub.