remix-run/remix · error · TypeError

mounts values must not overlap. Received "${mount.fileRootVa

Error message

mounts values must not overlap. Received "${mount.fileRootValue}" and "${otherMount.fileRootValue}", resolving to "${mount.fileRoot}" and "${otherMount.fileRoot}".

What it means

Two or more mounts resolve to overlapping file system directories (e.g. one is a prefix/ancestor of another after resolving against rootDir). validateNoOverlappingMounts rejects this because file lookup would be ambiguous.

Source

Thrown at packages/assets/src/lib/routes.ts:176

  return normalizePathname(`${root.replace(/\/+$/, '')}/${path.replace(/^\/+/, '')}`)
}

function getPathWithinRoot(root: string, value: string): string | null {
  if (value === root) return ''
  if (root === '/') return value.slice(1)
  if (!value.startsWith(`${root}/`)) return null
  return value.slice(root.length + 1)
}

function validateNoOverlappingMounts(mounts: readonly CompiledMount[]): void {
  for (let index = 0; index < mounts.length; index++) {
    let mount = mounts[index]

    for (let otherIndex = index + 1; otherIndex < mounts.length; otherIndex++) {
      let otherMount = mounts[otherIndex]

      if (rootsOverlap(mount.fileRoot, otherMount.fileRoot)) {
        throw new TypeError(
          `mounts values must not overlap. Received "${mount.fileRootValue}" and "${otherMount.fileRootValue}", resolving to "${mount.fileRoot}" and "${otherMount.fileRoot}".`,
        )
      }
    }
  }
}

function validateNoOverlappingUrlRoots(mounts: readonly CompiledMount[]): void {
  for (let index = 0; index < mounts.length; index++) {
    let mount = mounts[index]

    for (let otherIndex = index + 1; otherIndex < mounts.length; otherIndex++) {
      let otherMount = mounts[otherIndex]
      if (!rootsOverlap(mount.urlRoot, otherMount.urlRoot)) continue

      throw new TypeError(
        `mounts keys must not overlap. Received "${mount.urlRootKey}" and "${otherMount.urlRootKey}".`,
      )

View on GitHub (pinned to 9696913134)

Solutions

  1. Remove the redundant broader or narrower mount so each directory is mounted once
  2. Point overlapping mounts at distinct directories
  3. Consolidate and rely on nested URL keys instead of nested file roots

Example fix

// before
mounts: { '/': 'public', '/assets': 'public/assets' }
// after
mounts: { '/': 'public' }
Defensive patterns

Strategy: validation

Validate before calling

const resolved = Object.values(mounts).map((v) => resolve(rootDir, v))
for (let i = 0; i < resolved.length; i++)
  for (let j = i + 1; j < resolved.length; j++)
    if (resolved[i] === resolved[j] || resolved[i].startsWith(resolved[j] + sep) || resolved[j].startsWith(resolved[i] + sep))
      throw new Error('overlapping mounts')

Prevention

When it happens

Trigger: mounts: { '/a': 'public', '/b': 'public/assets' } — 'public/assets' is inside 'public'; also mounts resolving to the same directory, or '.' combined with any subdirectory.

Common situations: Adding a more specific mount while keeping the broad one; using '.' or '' as a catch-all mount alongside scoped mounts; different relative spellings ('public' vs 'public/' vs './public') that resolve to the same directory.

Related errors


AI-assisted analysis of remix-run/remix@9696913134 (2026-08-27). Data as JSON: /api/errors/17baa7646e10f3ac. Report an issue: GitHub.