Skip to content

Commit c792317

Browse files
authored
Clear up production build missing message for next start and next export (vercel#19777)
Adds an err.sh link to the production build missing message. Also clears up `valid` as `production`. Also fixes an edge case where an unhelpful error would be thrown because we checked for `.next` instead of `.next/BUILD_ID` Added the out directory location as the list line during export to make sure people know where the files are output. Fixes vercel#19778 Fixes vercel#19788
1 parent cf46655 commit c792317

File tree

9 files changed

+135
-5
lines changed

9 files changed

+135
-5
lines changed

errors/next-export-no-build-id.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# Could not find a production build
2+
3+
#### Why This Error Occurred
4+
5+
When running `next export` a production build is needed.
6+
7+
#### Possible Ways to Fix It
8+
9+
- Run `next build` to create a production build before running `next export`.
10+
- If your intention was to run the development server run `next dev` instead.
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# Could not find a production build
2+
3+
#### Why This Error Occurred
4+
5+
When running `next start` or a custom server in production mode a production build is needed.
6+
7+
#### Possible Ways to Fix It
8+
9+
- Run `next build` to create a production build before booting up the production server.
10+
- If your intention was to run the development server run `next dev` instead.

packages/next/cli/next-export.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ const nextExport: cliCommand = (argv) => {
6262

6363
exportApp(dir, options)
6464
.then(() => {
65-
printAndExit('Export successful', 0)
65+
printAndExit(`Export successful. Files written to ${options.outdir}`, 0)
6666
})
6767
.catch((err) => {
6868
printAndExit(err)

packages/next/export/index.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -164,9 +164,11 @@ export default async function exportApp(
164164
Log.info(`using build directory: ${distDir}`)
165165
}
166166

167-
if (!existsSync(distDir)) {
167+
const buildIdFile = join(distDir, BUILD_ID_FILE)
168+
169+
if (!existsSync(buildIdFile)) {
168170
throw new Error(
169-
`Build directory ${distDir} does not exist. Make sure you run "next build" before running "next start" or "next export".`
171+
`Could not find a production build in the '${distDir}' directory. Try building your app with 'next build' before starting the static export. https://err.sh/vercel/next.js/next-export-no-build-id`
170172
)
171173
}
172174

@@ -186,7 +188,7 @@ export default async function exportApp(
186188
)
187189
}
188190

189-
const buildId = readFileSync(join(distDir, BUILD_ID_FILE), 'utf8')
191+
const buildId = readFileSync(buildIdFile, 'utf8')
190192
const pagesManifest =
191193
!options.pages &&
192194
(require(join(

packages/next/next-server/server/next-server.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1899,7 +1899,7 @@ export default class Server {
18991899
} catch (err) {
19001900
if (!fs.existsSync(buildIdFile)) {
19011901
throw new Error(
1902-
`Could not find a valid build in the '${this.distDir}' directory! Try building your app with 'next build' before starting the server.`
1902+
`Could not find a production build in the '${this.distDir}' directory. Try building your app with 'next build' before starting the production server. https://err.sh/vercel/next.js/production-start-no-build-id`
19031903
)
19041904
}
19051905

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
module.exports = {
2+
onDemandEntries: {
3+
// Make sure entries are not getting disposed.
4+
maxInactiveAge: 1000 * 60 * 60,
5+
},
6+
rewrites() {
7+
// add a rewrite so the code isn't dead-code eliminated
8+
return [
9+
{
10+
source: '/some-rewrite',
11+
destination: '/',
12+
},
13+
]
14+
},
15+
redirects() {
16+
return [
17+
{
18+
source: '/redirect/me/to-about/:lang',
19+
destination: '/:lang/about',
20+
permanent: false,
21+
},
22+
{
23+
source: '/nonexistent',
24+
destination: '/about',
25+
permanent: false,
26+
},
27+
{
28+
source: '/shadowed-page',
29+
destination: '/about',
30+
permanent: false,
31+
},
32+
{
33+
source: '/redirect-query-test/:path',
34+
destination: '/about?foo=:path',
35+
permanent: false,
36+
},
37+
]
38+
},
39+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/* eslint-env jest */
2+
import { nextExport } from 'next-test-utils'
3+
import { join } from 'path'
4+
const appDir = join(__dirname, '../')
5+
jest.setTimeout(1000 * 60 * 5)
6+
7+
describe('next export without build', () => {
8+
it('should show error when there is no production build', async () => {
9+
const result = await nextExport(appDir, {}, { stderr: true, stdout: true })
10+
console.log(result.stdout, result.stderr)
11+
expect(result.stderr).toMatch(/Could not find a production build in the/)
12+
})
13+
})
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
module.exports = {
2+
onDemandEntries: {
3+
// Make sure entries are not getting disposed.
4+
maxInactiveAge: 1000 * 60 * 60,
5+
},
6+
rewrites() {
7+
// add a rewrite so the code isn't dead-code eliminated
8+
return [
9+
{
10+
source: '/some-rewrite',
11+
destination: '/',
12+
},
13+
]
14+
},
15+
redirects() {
16+
return [
17+
{
18+
source: '/redirect/me/to-about/:lang',
19+
destination: '/:lang/about',
20+
permanent: false,
21+
},
22+
{
23+
source: '/nonexistent',
24+
destination: '/about',
25+
permanent: false,
26+
},
27+
{
28+
source: '/shadowed-page',
29+
destination: '/about',
30+
permanent: false,
31+
},
32+
{
33+
source: '/redirect-query-test/:path',
34+
destination: '/about?foo=:path',
35+
permanent: false,
36+
},
37+
]
38+
},
39+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/* eslint-env jest */
2+
import { nextServer } from 'next-test-utils'
3+
import { join } from 'path'
4+
const appDir = join(__dirname, '../')
5+
jest.setTimeout(1000 * 60 * 5)
6+
7+
describe('Production Usage without production build', () => {
8+
it('should show error when there is no production build', async () => {
9+
expect(() => {
10+
nextServer({
11+
dir: appDir,
12+
dev: false,
13+
quiet: true,
14+
})
15+
}).toThrow(/Could not find a production build in the/)
16+
})
17+
})

0 commit comments

Comments
 (0)