From 40abd708e1f8117d3cc58396b8c3a1f5d79b1931 Mon Sep 17 00:00:00 2001 From: JJ Kasper Date: Mon, 24 Feb 2020 16:01:02 -0600 Subject: [PATCH] Show better error when non-array is returned from custom-routes (#10670) * Show better error when non-array is returned from custom-routes * bump Co-authored-by: Joe Haddad --- errors/routes-must-be-array.md | 42 +++++++++++++++++++ packages/next/build/index.ts | 17 ++++---- packages/next/lib/check-custom-routes.ts | 7 ++++ .../invalid-custom-routes/test/index.test.js | 32 +++++++++++++- 4 files changed, 90 insertions(+), 8 deletions(-) create mode 100644 errors/routes-must-be-array.md diff --git a/errors/routes-must-be-array.md b/errors/routes-must-be-array.md new file mode 100644 index 000000000000000..fd4a909dc111cd1 --- /dev/null +++ b/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', + }, + ] + }, + }, +} +``` diff --git a/packages/next/build/index.ts b/packages/next/build/index.ts index 7eb4ccd70189ed2..841f5472178b183 100644 --- a/packages/next/build/index.ts +++ b/packages/next/build/index.ts @@ -113,21 +113,24 @@ export default async function build(dir: string, conf = null): Promise { 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) { diff --git a/packages/next/lib/check-custom-routes.ts b/packages/next/lib/check-custom-routes.ts index b0dd787c271dba7..c3a538901323883 100644 --- a/packages/next/lib/check-custom-routes.ts +++ b/packages/next/lib/check-custom-routes.ts @@ -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 diff --git a/test/integration/invalid-custom-routes/test/index.test.js b/test/integration/invalid-custom-routes/test/index.test.js index e2c3d82c1968bc9..92b0b166309e9d5 100644 --- a/test/integration/invalid-custom-routes/test/index.test.js +++ b/test/integration/invalid-custom-routes/test/index.test.js @@ -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, ` @@ -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', () => {