diff --git a/dev-packages/e2e-tests/test-applications/nextjs-16-cacheComponents/app/capture-metadata/page.tsx b/dev-packages/e2e-tests/test-applications/nextjs-16-cacheComponents/app/capture-metadata/page.tsx
new file mode 100644
index 000000000000..15d10d763a6d
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/nextjs-16-cacheComponents/app/capture-metadata/page.tsx
@@ -0,0 +1,15 @@
+import { captureException } from '@sentry/nextjs';
+import type { Metadata } from 'next';
+
+/**
+ * Calling captureException synchronously inside generateMetadata
+ * during `next build` prerender (cacheComponents). uuid4 -> crypto.randomUUID() runs
+ */
+export const generateMetadata = (): Metadata => {
+ captureException(new Error('diagnostic: data missing for this page'));
+ return { title: 'capture-metadata' };
+};
+
+export default function Page() {
+ return
capture-metadata
;
+}
diff --git a/dev-packages/e2e-tests/test-applications/nextjs-16-cacheComponents/tests/cacheComponents.spec.ts b/dev-packages/e2e-tests/test-applications/nextjs-16-cacheComponents/tests/cacheComponents.spec.ts
index 0be0e2e6e3a6..29c90f5bc423 100644
--- a/dev-packages/e2e-tests/test-applications/nextjs-16-cacheComponents/tests/cacheComponents.spec.ts
+++ b/dev-packages/e2e-tests/test-applications/nextjs-16-cacheComponents/tests/cacheComponents.spec.ts
@@ -80,3 +80,10 @@ test('Should generate metadata async', async ({ page }) => {
await expect(page.locator('#todos-fetched')).toHaveText('Todos fetched: 5');
await expect(page).toHaveTitle('Product: 1');
});
+
+test('Should prerender a page that captures an exception in generateMetadata', async ({ page }) => {
+ await page.goto('/capture-metadata');
+
+ await expect(page).toHaveTitle('capture-metadata');
+ await expect(page.locator('h1')).toHaveText('capture-metadata');
+});
diff --git a/packages/nextjs/src/server/index.ts b/packages/nextjs/src/server/index.ts
index b22ba38ecd83..6ee3f9a5bb98 100644
--- a/packages/nextjs/src/server/index.ts
+++ b/packages/nextjs/src/server/index.ts
@@ -42,6 +42,9 @@ const globalWithInjectedValues = GLOBAL_OBJ as typeof GLOBAL_OBJ & {
_sentryRelease?: string;
};
+// Call at module level so `next build` prerender workers still register the runner without `init`
+prepareSafeIdGeneratorContext();
+
/**
* A passthrough error boundary for the server that doesn't depend on any react. Error boundaries don't catch SSR errors
* so they should simply be a passthrough.