Skip to content

Commit 77bedf3

Browse files
committed
fix: prevent revalidateTag/Path during render
also revert changes from #70446
1 parent 3ba9c10 commit 77bedf3

File tree

2 files changed

+33
-2
lines changed

2 files changed

+33
-2
lines changed

packages/next/src/server/web/spec-extension/revalidate.ts

+5
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,11 @@ function revalidate(tag: string, expression: string) {
6060
`Route ${store.route} used "${expression}" inside a function cached with "unstable_cache(...)" which is unsupported. To ensure revalidation is performed consistently it must always happen outside of renders and cached functions. See more info here: https://nextjs.org/docs/app/building-your-application/rendering/static-and-dynamic#dynamic-rendering`
6161
)
6262
}
63+
if (workUnitStore.phase === 'render') {
64+
throw new Error(
65+
`Route ${store.route} used "${expression}" during render which is unsupported. To ensure revalidation is performed consistently it must always happen outside of renders and cached functions. See more info here: https://nextjs.org/docs/app/building-your-application/rendering/static-and-dynamic#dynamic-rendering`
66+
)
67+
}
6368
}
6469

6570
// a route that makes use of revalidation APIs should be considered dynamic

test/e2e/app-dir/revalidatetag-rsc/revalidatetag-rsc.test.ts

+28-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import { nextTestSetup } from 'e2e-utils'
2-
import { retry } from 'next-test-utils'
2+
import { getRedboxHeader, retry } from 'next-test-utils'
33

44
describe('revalidateTag-rsc', () => {
5-
const { next } = nextTestSetup({
5+
const { next, isNextDev, isNextDeploy } = nextTestSetup({
66
files: __dirname,
77
})
88

@@ -20,4 +20,30 @@ describe('revalidateTag-rsc', () => {
2020
expect(randomNumber3).not.toEqual(randomNumber)
2121
})
2222
})
23+
24+
if (!isNextDeploy) {
25+
// skipped in deploy because it uses `next.cliOutput`
26+
it('should error if revalidateTag is called during render', async () => {
27+
const browser = await next.browser('/')
28+
await browser.elementByCss('#revalidate-via-page').click()
29+
30+
if (isNextDev) {
31+
await retry(async () => {
32+
expect(await getRedboxHeader(browser)).toContain(
33+
'Route /revalidate_via_page used "revalidateTag data"'
34+
)
35+
})
36+
} else {
37+
await retry(async () => {
38+
expect(
39+
await browser.eval('document.documentElement.innerHTML')
40+
).toContain('Application error: a server-side exception has occurred')
41+
})
42+
}
43+
44+
expect(next.cliOutput).toContain(
45+
'Route /revalidate_via_page used "revalidateTag data"'
46+
)
47+
})
48+
}
2349
})

0 commit comments

Comments
 (0)