fix: improve error when starting next without building (#62404)

Addresses #57066

Currently, a user running `next start` on an un-built Next.js project
receives a confusing uncaught error before the process just ends:

```
   ▲ Next.js 14.1.0
   - Local:        http://localhost:3000

[Error: ENOENT: no such file or directory, open '/home/flotwig/src/project/.next/BUILD_ID'] {
  errno: -2,
  code: 'ENOENT',
  syscall: 'open',
  path: '/home/flotwig/src/project/.next/BUILD_ID'
}
```

In my case, I ran into this because I had not worked with Next.js for a
while, and I forgot that `next dev` was used for local development, not
`next start`. I believe many of the confused users in #57066 are making
a similar mistake and not realizing it, due to the error message.

This PR catches an `ENOENT` when reading `BUILD_ID` and suggests that
the user `next build` or `next dev` to remove this friction point:

```
   ▲ Next.js 14.1.1-canary.69
   - Local:        http://localhost:3000

Error: Could not find a production build in the '.next' directory. Try building your app with 'next build' before starting the production server. https://nextjs.org/docs/messages/production-start-no-build-id
    at setupFsCheck (/home/flotwig/src/next.js/packages/next/src/server/lib/router-utils/filesystem.ts:157:13)
    at initialize (/home/flotwig/src/next.js/packages/next/src/server/lib/router-server.ts:90:21)
    at Server.<anonymous> (/home/flotwig/src/next.js/packages/next/src/server/lib/start-server.ts:295:28)
```

A few things probably need to be resolved before this PR can merge, I
would appreciate any input from Next.js maintainers.

- [x] Is this the best place to catch this? I am not familiar with the
Next.js codebase, so I just caught this in the most obvious way.
- [x] Can the error message be improved?
- [x] Add a test for the error in `test/development`

---------

Co-authored-by: JJ Kasper <jj@jjsweb.site>
This commit is contained in:
Zach Bloomquist 2024-02-27 13:34:22 -05:00 committed by GitHub
parent 036a4f60fc
commit f72debcf48
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 30 additions and 1 deletions

View file

@ -150,7 +150,14 @@ export async function setupFsCheck(opts: {
if (!opts.dev) {
const buildIdPath = path.join(opts.dir, opts.config.distDir, BUILD_ID_FILE)
buildId = await fs.readFile(buildIdPath, 'utf8')
try {
buildId = await fs.readFile(buildIdPath, 'utf8')
} catch (err: any) {
if (err.code !== 'ENOENT') throw err
throw new Error(
`Could not find a production build in the '${opts.config.distDir}' directory. Try building your app with 'next build' before starting the production server. https://nextjs.org/docs/messages/production-start-no-build-id`
)
}
try {
for (const file of await recursiveReadDir(publicFolderPath)) {

View file

@ -0,0 +1,22 @@
import { createNext } from 'e2e-utils'
describe('next start without next build', () => {
it('should show error when there is no production build', async () => {
const next = await createNext({
files: __dirname,
skipStart: true,
startCommand: `pnpm next start`,
})
await next.start()
await new Promise<void>((resolve, reject) => {
next.on('stderr', (msg) => {
if (msg.includes('Could not find a production build in the')) {
resolve()
}
})
})
await next.destroy()
})
})