{"record":{"id":"4000253caeb09d15","repo":"gatsbyjs/gatsby","slug":"you-can-only-have-single-instance-of-gatsby-plugin","errorCode":null,"errorMessage":"You can only have single instance of gatsby-plugin-layout in your gatsby-config.js","messagePattern":"You can only have single instance of gatsby-plugin-layout in your gatsby-config\\.js","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/gatsby-plugin-layout/src/gatsby-node.js","lineNumber":17,"sourceCode":"const path = require(`path`)\n\nlet didRunAlready = false\nlet absoluteComponentPath\n\nexports.onPreInit = ({ store }, { component }) => {\n  const defaultLayoutComponentPath = `src/layouts/index`\n  if (!component) {\n    // Default to `src/layouts/index.[js|jsx]` for drop-in replacement of v1 layouts\n    component = path.join(\n      store.getState().program.directory,\n      defaultLayoutComponentPath\n    )\n  }\n\n  if (didRunAlready) {\n    throw new Error(\n      `You can only have single instance of gatsby-plugin-layout in your gatsby-config.js`\n    )\n  }\n\n  didRunAlready = true\n  absoluteComponentPath = component\n}\n\nexports.onCreateWebpackConfig = ({ actions, plugins }) => {\n  actions.setWebpackConfig({\n    plugins: [\n      plugins.define({\n        GATSBY_LAYOUT_COMPONENT_PATH: JSON.stringify(absoluteComponentPath),\n      }),\n    ],\n  })\n}\n","sourceCodeStart":1,"sourceCodeEnd":35,"githubUrl":"https://github.com/gatsbyjs/gatsby/blob/8b06340921ffdf23125a365b9c9923690cb62ce6/packages/gatsby-plugin-layout/src/gatsby-node.js#L1-L35","documentation":"Thrown by gatsby-plugin-layout's onPreInit when the plugin's module-level didRunAlready flag is already true, i.e. onPreInit has executed once already in this Node process. The plugin stores absoluteComponentPath in module scope, so a second initialization would overwrite it; the guard hard-blocks duplicate registration.","triggerScenarios":"Listing gatsby-plugin-layout more than once in the plugins array of gatsby-config.js; including a starter or theme that itself adds gatsby-plugin-layout while you also list it; a composite config (gatsby-config + .gatsby-config presets) that merges the plugin in twice.","commonSituations":"User adds gatsby-plugin-layout manually while a theme (e.g. a blog theme) already depends on it; copying config snippets from docs without checking duplicates; upgrading a theme that newly added the plugin.","solutions":["Search gatsby-config.js (and any presets/themes) for duplicate gatsby-plugin-layout entries and keep only one.","Run `gatsby plugin` to list resolved plugins and confirm the plugin appears once.","If a theme brings it in, remove your own explicit entry and let the theme own it."],"exampleFix":"// before (duplicate entry)\nplugins: ['gatsby-plugin-layout', { resolve: 'gatsby-theme-x', options: {} }, 'gatsby-plugin-layout']\n// after (single entry)\nplugins: ['gatsby-plugin-layout', { resolve: 'gatsby-theme-x', options: {} }]","handlingStrategy":"validation","validationCode":"const layoutPlugins = plugins.filter(p => (typeof p === 'string' ? p : p.resolve) === 'gatsby-plugin-layout')\nif (layoutPlugins.length > 1) throw new Error('duplicate gatsby-plugin-layout')","typeGuard":"const isSingleLayoutPlugin = (plugins: any[]): boolean =>\n  plugins.filter(p => (typeof p === 'string' ? p : p?.resolve) === 'gatsby-plugin-layout').length === 1","tryCatchPattern":null,"preventionTips":["List gatsby-plugin-layout exactly once in gatsby-config.js.","Run `gatsby plugin` to confirm no duplicates from themes.","Let a theme own the plugin instead of re-adding it."],"tags":["gatsby-plugin-layout","plugin-config","duplicate","gatsby-node"],"backgroundTag":null,"analyzedSha":"8b06340921ffdf23125a365b9c9923690cb62ce6","analyzedAt":"2026-08-13T02:36:21.405Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}