Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Show better error when non-array is returned from custom-routes #10670

Merged
merged 4 commits into from Feb 24, 2020
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
42 changes: 42 additions & 0 deletions errors/routes-must-be-array.md
@@ -0,0 +1,42 @@
# Custom Routes must return an array

#### Why This Error Occurred

When defining custom routes an array wasn't returned from either `headers`, `rewrites`, or `redirects`.

#### Possible Ways to Fix It

Make sure to return an array that contains the routes.

**Before**

```js
// next.config.js
module.exports = {
experimental: {
async rewrites() {
return {
source: '/feedback',
destination: '/feedback/general',
}
},
},
}
```

**After**

```js
module.exports = {
experimental: {
async rewrites() {
return [
{
source: '/feedback',
destination: '/feedback/general',
},
]
},
},
}
```
17 changes: 10 additions & 7 deletions packages/next/build/index.ts
Expand Up @@ -113,21 +113,24 @@ export default async function build(dir: string, conf = null): Promise<void> {
const { target } = config
const buildId = await generateBuildId(config.generateBuildId, nanoid)
const distDir = path.join(dir, config.distDir)
const headers: Header[] = []
const rewrites: Rewrite[] = []
const redirects: Redirect[] = []
const headers: Header[] = []

if (typeof config.experimental.redirects === 'function') {
redirects.push(...(await config.experimental.redirects()))
checkCustomRoutes(redirects, 'redirect')
const _redirects = await config.experimental.redirects()
checkCustomRoutes(_redirects, 'redirect')
redirects.push(..._redirects)
}
if (typeof config.experimental.rewrites === 'function') {
rewrites.push(...(await config.experimental.rewrites()))
checkCustomRoutes(rewrites, 'rewrite')
const _rewrites = await config.experimental.rewrites()
checkCustomRoutes(_rewrites, 'rewrite')
rewrites.push(..._rewrites)
}
if (typeof config.experimental.headers === 'function') {
headers.push(...(await config.experimental.headers()))
checkCustomRoutes(headers, 'header')
const _headers = await config.experimental.headers()
checkCustomRoutes(_headers, 'header')
headers.push(..._headers)
}

if (ciEnvironment.isCI) {
Expand Down
7 changes: 7 additions & 0 deletions packages/next/lib/check-custom-routes.ts
Expand Up @@ -78,6 +78,13 @@ export default function checkCustomRoutes(
routes: Redirect[] | Header[] | Rewrite[],
type: RouteType
): void {
if (!Array.isArray(routes)) {
throw new Error(
`${type}s must return an array, received ${typeof routes}.\n` +
`See here for more info: https://err.sh/next.js/routes-must-be-array`
)
}

let numInvalidRoutes = 0
let hadInvalidStatus = false

Expand Down
32 changes: 31 additions & 1 deletion test/integration/invalid-custom-routes/test/index.test.js
Expand Up @@ -9,7 +9,7 @@ jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000 * 60 * 2
let appDir = join(__dirname, '..')
const nextConfigPath = join(appDir, 'next.config.js')

const writeConfig = async (routes = [], type = 'redirects') => {
const writeConfig = async (routes, type = 'redirects') => {
await fs.writeFile(
nextConfigPath,
`
Expand Down Expand Up @@ -322,6 +322,36 @@ const runTests = () => {
expect(stderr).toContain(`Reason: Unexpected MODIFIER at 10, expected END`)
expect(stderr).toContain(`/learning/?`)
})

it('should show valid error when non-array is returned from rewrites', async () => {
await writeConfig(
{
source: '/feedback/(?!general)',
destination: '/feedback/general',
},
'rewrites'
)

const stderr = await getStderr()

expect(stderr).toContain(`rewrites must return an array, received object`)
})

it('should show valid error when non-array is returned from redirects', async () => {
await writeConfig(false, 'redirects')

const stderr = await getStderr()

expect(stderr).toContain(`redirects must return an array, received boolean`)
})

it('should show valid error when non-array is returned from headers', async () => {
await writeConfig(undefined, 'headers')

const stderr = await getStderr()

expect(stderr).toContain(`headers must return an array, received undefined`)
})
}

describe('Errors on invalid custom routes', () => {
Expand Down