gatsbyjs/gatsby · error · Error

Gatsby can't differentiate between themes ${matchingThemes.m

Error message

Gatsby can't differentiate between themes ${matchingThemes.map(theme => theme.themeName).join(` and `)} for path ${filepath}

What it means

Theme component shadowing matches a file path against each theme's `src/` directory. After de-duplicating, if two distinct themes both claim the path (their `src` prefixes both match), Gatsby cannot decide which theme owns the shadowed component and aborts.

Source

Thrown at packages/gatsby/src/internal-plugins/webpack-theme-component-shadowing/index.js:253

    }
    return null
  }

  getThemeAndComponent(filepath) {
    // find out which theme's src/components dir we're requiring from
    const allMatchingThemes = this.themes.filter(({ themeDir }) =>
      filepath.startsWith(path.join(themeDir, `src`))
    )

    // The same theme can be included twice in the themes list causing multiple
    // matches. This case should only be counted as a single match for that theme.
    const matchingThemes = _.uniqBy(allMatchingThemes, `themeName`)

    // 0 matching themes happens a lot for paths we don't want to handle
    // > 1 matching theme means we have a path like
    //   `gatsby-theme-blog/src/components/gatsby-theme-something/src/components`
    if (matchingThemes.length > 1) {
      throw new Error(
        `Gatsby can't differentiate between themes ${matchingThemes
          .map(theme => theme.themeName)
          .join(` and `)} for path ${filepath}`
      )
    }

    if (matchingThemes.length === 0) {
      return [null, null]
    }

    const theme = matchingThemes[0]

    // get the location of the component relative to its theme's src/
    const [, component] = filepath.split(path.join(theme.themeDir, `src`))

    return [theme, component]
  }

View on GitHub (pinned to 8b06340921)

Solutions

  1. Rename the inner theme's package/`themeDir` so its `src` path is not a prefix collision with the outer theme.
  2. Move the shadowed component out of the colliding path.
  3. Avoid having one theme shadow another theme inside a directory whose name equals the outer theme's `src` tree.
Defensive patterns

Strategy: validation

Validate before calling

// For theme authors: assert no two theme dirs share a prefix collision.
function assertNoShadowCollision(themes) {
  const dirs = themes.map(t => path.join(t.themeDir, "src"))
  for (let i = 0; i < dirs.length; i++) {
  for (let j = i + 1; j < dirs.length; j++) {
  if (dirs[i].startsWith(dirs[j]) || dirs[j].startsWith(dirs[i])) {
  throw new Error(`Theme dirs collide: ${dirs[i]} <-> ${dirs[j]}`)
  }
  }
  }
}

Prevention

When it happens

Trigger: A path such as `gatsby-theme-blog/src/components/gatsby-theme-something/src/...` where one theme's directory prefix is nested inside another theme's prefix, yielding two unique matches.

Common situations: A theme that itself depends on another theme and re-exports components under a path that starts with the outer theme's `src`; renamed/duplicated theme packages sharing a `themeDir` prefix.

Related errors


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