remix-run/remix · error · TypeError

mounts keys must not overlap. Received "${mount.urlRootKey}"

Error message

mounts keys must not overlap. Received "${mount.urlRootKey}" and "${otherMount.urlRootKey}".

What it means

Two or more mounts keys (URL roots) overlap after normalization — one URL root is a prefix of another (or they are equal). validateNoOverlappingUrlRoots rejects this during compileRoutes because request routing would be ambiguous.

Source

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

      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}".`,
      )
    }
  }
}

function rootsOverlap(root: string, otherRoot: string): boolean {
  return (
    root === otherRoot ||
    root === '/' ||
    otherRoot === '/' ||
    root.startsWith(`${otherRoot}/`) ||
    otherRoot.startsWith(`${root}/`)
  )
}

function isUnresolvedPathError(error: unknown, filePath: string): boolean {
  // Windows reports UNKNOWN rather than ENOENT when a UNC share cannot be reached.

View on GitHub (pinned to 9696913134)

Solutions

  1. Remove the overlapping parent or child URL mount and serve nested paths from the parent's directory structure
  2. If you need a different directory for a sub-path, restructure so URL roots are siblings, not nested
  3. Check for trailing-slash duplicates when generating mounts programmatically

Example fix

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

Strategy: validation

Validate before calling

const roots = Object.keys(mounts).map((k) => k.replace(/\/+$/, '') || '/')
for (let i = 0; i < roots.length; i++)
  for (let j = i + 1; j < roots.length; j++)
    if (roots[i] === roots[j] || roots[j].startsWith(roots[i] + '/'))
      throw new Error('overlapping mount keys')

Prevention

When it happens

Trigger: mounts: { '/assets': 'a', '/assets/img': 'b' } — '/assets/img' is nested under '/assets'; also duplicate keys after trailing-slash normalization like '/assets' and '/assets/'.

Common situations: Adding a nested URL scope for a different directory while the parent URL is already mounted; trailing-slash or basePath inconsistencies making two keys normalize identically; evolving config where an old mount was left in place.

Related errors


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