vercel/next.js · error · Error

> `pages` and `app` directories should be under the same fol

Error message

> `pages` and `app` directories should be under the same folder

What it means

Thrown by findPagesDir() when both a `pages` and an `app` directory exist but their parent directories differ. Next.js requires both routing roots to share the same parent folder so route resolution is unambiguous; mixing locations (e.g. pages/ at root and app/ under src/) breaks the shared route namespace.

Source

Thrown at packages/next/src/lib/find-pages-dir.ts:32

export function findPagesDir(dir: string): {
  pagesDir: string | undefined
  appDir: string | undefined
} {
  const pagesDir = findDir(dir, 'pages') || undefined
  const appDir = findDir(dir, 'app') || undefined

  if (appDir == null && pagesDir == null) {
    throw new Error(
      "> Couldn't find any `pages` or `app` directory. Please create one under the project root"
    )
  }

  if (pagesDir && appDir) {
    const pagesParent = path.dirname(pagesDir)
    const appParent = path.dirname(appDir)
    if (pagesParent !== appParent) {
      throw new Error(
        '> `pages` and `app` directories should be under the same folder'
      )
    }
  }

  return {
    pagesDir,
    appDir,
  }
}

View on GitHub (pinned to 0ae8c72462)

Solutions

  1. Move both directories under the same parent (either both at root: ./pages + ./app, or both under src: ./src/pages + ./src/app).
  2. Delete the unused router folder if you have fully migrated (e.g. remove pages/ once app/ is the source of truth).
  3. Verify there are no stale copies of pages/ or app/ left behind by a move operation.

Example fix

# before: mismatched parents
# ./pages/            <- root
# ./src/app/          <- src
next dev  # error
# after: align both under src
mv pages src/pages
# now ./src/pages and ./src/app share parent
next dev
Defensive patterns

Strategy: validation

Validate before calling

import fs from 'fs'
import path from 'path'
function assertRoutingDirsColocated(root: string) {
  const pages = ['pages','src/pages'].map((c)=>path.join(root,c)).find(fs.existsSync)
  const app = ['app','src/app'].map((c)=>path.join(root,c)).find(fs.existsSync)
  if (pages && app && path.dirname(pages) !== path.dirname(app)) {
    throw new Error('pages/ and app/ must share the same parent directory')
  }
}

Prevention

When it happens

Trigger: The project has, for example, ./pages and ./src/app, or ./src/pages and ./app. path.dirname of each differs, triggering the guard. Common during incremental migration from Pages Router to App Router.

Common situations: Migrating to the App Router by creating app/ inside src/ while the old pages/ remains at the root; scaffolding tools that put one router under src and another at root; or a half-finished restructure. Also after moving source into src/ and forgetting to relocate one of the routing folders.

Related errors


AI-assisted analysis of vercel/next.js@0ae8c72462 (2026-08-06). Data as JSON: /api/errors/98a32fa4ed53ad86. Report an issue: GitHub.