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
- Move both directories under the same parent (either both at root: ./pages + ./app, or both under src: ./src/pages + ./src/app).
- Delete the unused router folder if you have fully migrated (e.g. remove pages/ once app/ is the source of truth).
- 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
- During Pages→App migration, keep both routers under the same parent (root or src).
- After migration, delete the unused router folder to avoid ambiguity.
- Add a lint/prebuild check that compares dirname(pages) and dirname(app).
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
- > Couldn't find any `pages` or `app` directory. Please creat
- The provided export path '${pathname}' doesn't match the '${
- Failed to resolve pattern "${patterns.join(',')}": ${error.m
- Command failed: ${command} ${args.join(' ')} (exit ${code})
- Missing ${NEXT_BIN}. Build Next.js first (pnpm --filter=next
AI-assisted analysis of vercel/next.js@0ae8c72462 (2026-08-06).
Data as JSON: /api/errors/98a32fa4ed53ad86.
Report an issue: GitHub.