diff --git a/lib/app/client.js b/lib/app/client.js
index d210a0c24b..c2c5b0c4bd 100644
--- a/lib/app/client.js
+++ b/lib/app/client.js
@@ -292,11 +292,28 @@ async function render (to, from, next) {
// Call .validate()
let isValid = true
- Components.forEach((Component) => {
- if (!isValid) return
- if (typeof Component.options.validate !== 'function') return
- isValid = Component.options.validate(app.context)
- })
+ let validationError
+ try {
+ for (const Component of Components) {
+ if (typeof Component.options.validate !== 'function') {
+ continue
+ }
+
+ isValid = await Component.options.validate(app.context)
+
+ if (!isValid) {
+ break
+ }
+ }
+ } catch (validationError) {
+ // ...If .validate() threw an error
+ this.error({
+ statusCode: validationError.statusCode || '500',
+ message: validationError.message
+ })
+ return next()
+ }
+
// ...If .validate() returned false
if (!isValid) {
this.error({ statusCode: 404, message: `<%= messages.error_404 %>` })
diff --git a/lib/app/server.js b/lib/app/server.js
index 76070d8504..4e0f1c5e78 100644
--- a/lib/app/server.js
+++ b/lib/app/server.js
@@ -154,11 +154,28 @@ export default async (ssrContext) => {
** Call .validate()
*/
let isValid = true
- Components.forEach((Component) => {
- if (!isValid) return
- if (typeof Component.options.validate !== 'function') return
- isValid = Component.options.validate(app.context)
- })
+ let validationError
+ try {
+ for (const Component of Components) {
+ if (typeof Component.options.validate !== 'function') {
+ continue
+ }
+
+ isValid = await Component.options.validate(app.context)
+
+ if (!isValid) {
+ break
+ }
+ }
+ } catch (validationError) {
+ // ...If .validate() threw an error
+ app.context.error({
+ statusCode: validationError.statusCode || '500',
+ message: validationError.message
+ })
+ return renderErrorPage()
+ }
+
// ...If .validate() returned false
if (!isValid) {
// Don't server-render the page in generate mode
diff --git a/test/e2e/basic.browser.test.js b/test/e2e/basic.browser.test.js
index 70c73eed73..86442cceee 100644
--- a/test/e2e/basic.browser.test.js
+++ b/test/e2e/basic.browser.test.js
@@ -123,12 +123,27 @@ describe('basic browser', () => {
expect(error.message).toBe('This page could not be found')
})
+ test('/validate-async should display a 404', async () => {
+ await page.nuxt.navigate('/validate-async')
+
+ const error = await page.nuxt.errorData()
+
+ expect(error.statusCode).toBe(404)
+ expect(error.message).toBe('This page could not be found')
+ })
+
test('/validate?valid=true', async () => {
await page.nuxt.navigate('/validate?valid=true')
expect(await page.$text('h1')).toBe('I am valid')
})
+ test('/validate-async?valid=true', async () => {
+ await page.nuxt.navigate('/validate-async?valid=true')
+
+ expect(await page.$text('h1')).toBe('I am valid')
+ })
+
test('/redirect', async () => {
await page.nuxt.navigate('/redirect')
diff --git a/test/fixtures/basic/pages/validate-async.vue b/test/fixtures/basic/pages/validate-async.vue
new file mode 100644
index 0000000000..8637d0f81a
--- /dev/null
+++ b/test/fixtures/basic/pages/validate-async.vue
@@ -0,0 +1,15 @@
+
+ I am valid
+
+
+
diff --git a/test/unit/basic.ssr.test.js b/test/unit/basic.ssr.test.js
index e56a33de73..f9e6f6a6f5 100644
--- a/test/unit/basic.ssr.test.js
+++ b/test/unit/basic.ssr.test.js
@@ -96,11 +96,21 @@ describe('basic ssr', () => {
expect(html.includes('This page could not be found')).toBe(true)
})
+ test('/validate-async should display a 404', async () => {
+ const { html } = await nuxt.renderRoute('/validate-async')
+ expect(html.includes('This page could not be found')).toBe(true)
+ })
+
test('/validate?valid=true', async () => {
const { html } = await nuxt.renderRoute('/validate?valid=true')
expect(html.includes('