diff --git a/dev-packages/e2e-tests/test-applications/nextjs-14/app/generation-functions/page.tsx b/dev-packages/e2e-tests/test-applications/nextjs-14/app/generation-functions/page.tsx
index 92bee1dbac4b..0d8f1841ea9d 100644
--- a/dev-packages/e2e-tests/test-applications/nextjs-14/app/generation-functions/page.tsx
+++ b/dev-packages/e2e-tests/test-applications/nextjs-14/app/generation-functions/page.tsx
@@ -7,33 +7,31 @@ export default function Page() {
return
Hello World!
;
}
-export async function generateMetadata({
- searchParams,
-}: {
- searchParams: { [key: string]: string | string[] | undefined };
-}) {
+export async function generateMetadata({ searchParams }: { searchParams: any }) {
+ // We need to dynamically check for this because Next.js made the API async for Next.js 15 and we use this test in canary tests
+ const normalizedSearchParams = await searchParams;
+
Sentry.setTag('my-isolated-tag', true);
Sentry.setTag('my-global-scope-isolated-tag', getDefaultIsolationScope().getScopeData().tags['my-isolated-tag']); // We set this tag to be able to assert that the previously set tag has not leaked into the global isolation scope
- if (searchParams['shouldThrowInGenerateMetadata']) {
+ if (normalizedSearchParams['shouldThrowInGenerateMetadata']) {
throw new Error('generateMetadata Error');
}
return {
- title: searchParams['metadataTitle'] ?? 'not set',
+ title: normalizedSearchParams['metadataTitle'] ?? 'not set',
};
}
-export function generateViewport({
- searchParams,
-}: {
- searchParams: { [key: string]: string | undefined };
-}) {
- if (searchParams['shouldThrowInGenerateViewport']) {
+export async function generateViewport({ searchParams }: { searchParams: any }) {
+ // We need to dynamically check for this because Next.js made the API async for Next.js 15 and we use this test in canary tests
+ const normalizedSearchParams = await searchParams;
+
+ if (normalizedSearchParams['shouldThrowInGenerateViewport']) {
throw new Error('generateViewport Error');
}
return {
- themeColor: searchParams['viewportThemeColor'] ?? 'black',
+ themeColor: normalizedSearchParams['viewportThemeColor'] ?? 'black',
};
}
diff --git a/dev-packages/e2e-tests/test-applications/nextjs-14/app/propagation/utils.ts b/dev-packages/e2e-tests/test-applications/nextjs-14/app/propagation/utils.ts
index a065c53ee4c9..249efabe58f3 100644
--- a/dev-packages/e2e-tests/test-applications/nextjs-14/app/propagation/utils.ts
+++ b/dev-packages/e2e-tests/test-applications/nextjs-14/app/propagation/utils.ts
@@ -26,8 +26,8 @@ export function makeHttpRequest(url: string) {
});
}
-export function checkHandler() {
- const headerList = headers();
+export async function checkHandler() {
+ const headerList = await headers();
const headerObj: Record = {};
headerList.forEach((value, key) => {
diff --git a/dev-packages/e2e-tests/test-applications/nextjs-15/app/ppr-error/[param]/page.tsx b/dev-packages/e2e-tests/test-applications/nextjs-15/app/ppr-error/[param]/page.tsx
index ec2b2b1232c7..c67513e0e4fd 100644
--- a/dev-packages/e2e-tests/test-applications/nextjs-15/app/ppr-error/[param]/page.tsx
+++ b/dev-packages/e2e-tests/test-applications/nextjs-15/app/ppr-error/[param]/page.tsx
@@ -3,10 +3,13 @@ import * as Sentry from '@sentry/nextjs';
export default async function Page({
searchParams,
}: {
- searchParams: { id?: string };
+ searchParams: any;
}) {
+ // We need to dynamically check for this because Next.js made the API async for Next.js 15 and we use this test in canary tests
+ const normalizedSearchParams = await searchParams;
+
try {
- console.log(searchParams.id); // Accessing a field on searchParams will throw the PPR error
+ console.log(normalizedSearchParams.id); // Accessing a field on searchParams will throw the PPR error
} catch (e) {
Sentry.captureException(e); // This error should not be reported
await new Promise(resolve => setTimeout(resolve, 1000)); // Wait for any async event processors to run
diff --git a/dev-packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/parameter/[...parameters]/page.tsx b/dev-packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/parameter/[...parameters]/page.tsx
index 31fa4ee21be5..f09f06875c3a 100644
--- a/dev-packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/parameter/[...parameters]/page.tsx
+++ b/dev-packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/parameter/[...parameters]/page.tsx
@@ -1,10 +1,14 @@
+import { use } from 'react';
import { ClientErrorDebugTools } from '../../../../components/client-error-debug-tools';
-export default function Page({ params }: { params: Record }) {
+export default function Page({ params }: any) {
+ // We need to dynamically check for this because Next.js made the API async for Next.js 15 and we use this test in canary tests
+ const normalizedParams = 'then' in params ? use(params) : params;
+
return (
Page (/client-component/[...parameters])
-
Params: {JSON.stringify(params['parameters'])}
+
Params: {JSON.stringify(normalizedParams['parameters'])}
);
diff --git a/dev-packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/parameter/[parameter]/page.tsx b/dev-packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/parameter/[parameter]/page.tsx
index 2b9c28b922ac..514a0833c998 100644
--- a/dev-packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/parameter/[parameter]/page.tsx
+++ b/dev-packages/e2e-tests/test-applications/nextjs-app-dir/app/client-component/parameter/[parameter]/page.tsx
@@ -1,10 +1,14 @@
+import { use } from 'react';
import { ClientErrorDebugTools } from '../../../../components/client-error-debug-tools';
-export default function Page({ params }: { params: Record }) {
+export default function Page({ params }: any) {
+ // We need to dynamically check for this because Next.js made the API async for Next.js 15 and we use this test in canary tests
+ const normalizedParams = 'then' in params ? use(params) : params;
+
return (
Page (/client-component/[parameter])
-
Parameter: {JSON.stringify(params['parameter'])}
+
Parameter: {JSON.stringify(normalizedParams['parameter'])}
);
diff --git a/dev-packages/e2e-tests/test-applications/nextjs-app-dir/app/server-component/parameter/[...parameters]/page.tsx b/dev-packages/e2e-tests/test-applications/nextjs-app-dir/app/server-component/parameter/[...parameters]/page.tsx
index 5d9d6c8262c5..63d0e7b53f0b 100644
--- a/dev-packages/e2e-tests/test-applications/nextjs-app-dir/app/server-component/parameter/[...parameters]/page.tsx
+++ b/dev-packages/e2e-tests/test-applications/nextjs-app-dir/app/server-component/parameter/[...parameters]/page.tsx
@@ -1,12 +1,16 @@
+import { use } from 'react';
import { ClientErrorDebugTools } from '../../../../components/client-error-debug-tools';
export const dynamic = 'force-dynamic';
-export default async function Page({ params }: { params: Record }) {
+export default function Page({ params }: any) {
+ // We need to dynamically check for this because Next.js made the API async for Next.js 15 and we use this test in canary tests
+ const normalizedParams = 'then' in params ? use(params) : params;
+
return (
Page (/server-component/[...parameters])
-
Params: {JSON.stringify(params['parameters'])}
+
Params: {JSON.stringify(normalizedParams['parameters'])}
);
diff --git a/dev-packages/e2e-tests/test-applications/nextjs-app-dir/app/server-component/parameter/[parameter]/page.tsx b/dev-packages/e2e-tests/test-applications/nextjs-app-dir/app/server-component/parameter/[parameter]/page.tsx
index f88fe1cd4a06..98ecb7352ad2 100644
--- a/dev-packages/e2e-tests/test-applications/nextjs-app-dir/app/server-component/parameter/[parameter]/page.tsx
+++ b/dev-packages/e2e-tests/test-applications/nextjs-app-dir/app/server-component/parameter/[parameter]/page.tsx
@@ -1,12 +1,16 @@
+import { use } from 'react';
import { ClientErrorDebugTools } from '../../../../components/client-error-debug-tools';
export const dynamic = 'force-dynamic';
-export default async function Page({ params }: { params: Record }) {
+export default function Page({ params }: any) {
+ // We need to dynamically check for this because Next.js made the API async for Next.js 15 and we use this test in canary tests
+ const normalizedParams = 'then' in params ? use(params) : params;
+
return (
Page (/server-component/[parameter])
-
Parameter: {JSON.stringify(params['parameter'])}
+
Parameter: {JSON.stringify(normalizedParams['parameter'])}
);
diff --git a/packages/nextjs/src/common/withServerActionInstrumentation.ts b/packages/nextjs/src/common/withServerActionInstrumentation.ts
index 14c701638ee5..c1633d8fab1b 100644
--- a/packages/nextjs/src/common/withServerActionInstrumentation.ts
+++ b/packages/nextjs/src/common/withServerActionInstrumentation.ts
@@ -15,7 +15,18 @@ import { vercelWaitUntil } from './utils/vercelWaitUntil';
interface Options {
formData?: FormData;
- headers?: Headers;
+
+ /**
+ * Headers as returned from `headers()`.
+ *
+ * Currently accepts both a plain `Headers` object and `Promise` to be compatible with async APIs introduced in Next.js 15: https://github.com/vercel/next.js/pull/68812
+ */
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ headers?: Headers | Promise;
+
+ /**
+ * Whether the server action response should be included in any events captured within the server action.
+ */
recordResponse?: boolean;
}
@@ -55,16 +66,17 @@ async function withServerActionInstrumentationImplementation> {
return escapeNextjsTracing(() => {
- return withIsolationScope(isolationScope => {
+ return withIsolationScope(async isolationScope => {
const sendDefaultPii = getClient()?.getOptions().sendDefaultPii;
let sentryTraceHeader;
let baggageHeader;
const fullHeadersObject: Record = {};
try {
- sentryTraceHeader = options.headers?.get('sentry-trace') ?? undefined;
- baggageHeader = options.headers?.get('baggage');
- options.headers?.forEach((value, key) => {
+ const awaitedHeaders: Headers = await options.headers;
+ sentryTraceHeader = awaitedHeaders?.get('sentry-trace') ?? undefined;
+ baggageHeader = awaitedHeaders?.get('baggage');
+ awaitedHeaders?.forEach((value, key) => {
fullHeadersObject[key] = value;
});
} catch (e) {