getsentry / sentry-javascript

Official Sentry SDKs for JavaScript
https://sentry.io
MIT License
7.78k stars 1.52k forks source link

Next.js Monorepo Build Fails After Sentry 8.7.0 Upgrade Due to Module Resolution Error #12362

Open Palmaswell opened 1 month ago

Palmaswell commented 1 month ago

Is there an existing issue for this?

How do you use Sentry?

Sentry Saas (sentry.io)

Which SDK are you using?

@sentry/nextjs

SDK Version

8.7.0

Framework Version

@sentry/nextjs@^8.7.0", @sentry/node@^8.7.0, @sentry/profiling-node@^8.7.0

Link to Sentry event

No response

SDK Setup

Client


import * as Sentry from "@sentry/nextjs";
const SENTRY_DSN =
  process.env.SENTRY_DSN ||
  process.env.NEXT_PUBLIC_SENTRY_DSN;

Sentry.init({
  enabled: process.env.VERCEL_ENV === "production",
  dsn: SENTRY_DSN,
  tracesSampleRate: 0.8,
  replaysSessionSampleRate: 0.1,
  replaysOnErrorSampleRate: 1.0,
  // Note: if you want to override the automatic release value, do not set a
  // `release` value here - use the environment variable `SENTRY_RELEASE`, so
  // that it will also get attached to your source maps
});

Sentry.addEventProcessor((event, hint) => {
  if (hint.originalException?.logs) {
    event.tags ??= {};
    event.tags["squads-program-error"] = true;
    event.extra = {
      ...event.extra,
      programLogs: hint.originalException.logs,
    };
  }

  return event;
});

Instrumentation.ts

import * as Sentry from "@sentry/nextjs";

const SENTRY_DSN =
  process.env.SENTRY_DSN ||
  process.env.NEXT_PUBLIC_SENTRY_DSN;

export async function register() {
  if (process.env.NEXT_RUNTIME === "nodejs") {
    const { nodeProfilingIntegration } = await import("@sentry/profiling-node");

    Sentry.init({
      enabled: process.env.VERCEL_ENV === "production",
      dsn: SENTRY_DSN,
      tracesSampleRate: 0.8,
      profilesSampleRate: 1.0,
      integrations: [nodeProfilingIntegration()],
    });
  }

  if (process.env.NEXT_RUNTIME === "edge") {
    Sentry.init({
      enabled: process.env.VERCEL_ENV === "production",
      dsn: SENTRY_DSN,
      tracesSampleRate: 0.8,
    });
  }
}

Next.JS Config

import { withSentryConfig } from "@sentry/nextjs";
import { createVanillaExtractPlugin } from "@vanilla-extract/next-plugin";

const withVanillaExtract = createVanillaExtractPlugin({
  outputCss: true,
});

/** @type {import('next').NextConfig} */
const nextConfig = {
  reactStrictMode: true,
  transpilePackages: ["@squads/ui"],
  experimental: {
    instrumentationHook: true,
    serverComponentsExternalPackages: ["@sentry/profiling-node"],
  },
  images: {
    remotePatterns: [
      {
        protocol: "https",
        hostname: "**",
      },
    ],
  },
  redirects: async () => {
    return [{ source: "/", destination: "/squads", permanent: true }];
  },
  webpack: (config, { nextRuntime }) => {
    if (nextRuntime === "edge") {
      config.externals.push({
        "node:crypto": "{}",
        stream: "{}",
      });
    }

    config.externals.push({
      "@sentry/profiling-node": "commonjs @sentry/profiling-node",
    });

    config.resolve.fallback = {
      ...config.resolve.fallback, 
      fs: false, 
    };
    return config;
  },
};

export default withSentryConfig(withVanillaExtract(nextConfig), { 
    silent: true, 
    hideSourceMaps: true 
    },
);

Steps to Reproduce

With meticulous attention, I diligently followed all the steps outlined in the documentation to address the issue.

  1. First, I upgraded to the latest seven versions (7.116.0) and then diligently fixed all deprecations in the project's Next.js package.
  2. I introduced the Next.js instrumentation file and imported the server and edge runtime configurations. Until this step, everything was working fine in our Yarn multi-package (mono) repo.
  3. We upgraded the packages mentioned above from 7.116.0 to 8.7.0.
  4. Removed the server and edge configuration files and moved the configuration to the instrumentation file.
  5. I updated the withSentryConfig in the Next.js config, as it now only accepts two arguments.
  6. Dynamically imported integrations module to the corresponding environment if statement.
  7. Rebuild mono repo packages with yarn.
  8. At this point, I could no longer build the Next.js project next build. Running dev was still possible, though, next start.

Expected Result

I expect to successfully upgrade the three packages and start and build the Next.js package as usual.

Actual Result

I continuously get the same error when running a next build.

Please note that I also tried:

  1. Upgrading to a different 8 version, like 8.0.0.
  2. Remove the @sentry/profiling-node package.
  3. Delete the yarn.lock file, all without success.
web:build:    Generating static pages (0/6) ...

TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string. Received type number (96184)
--
17:59:05.576 | web:build:     at new NodeError (node:internal/errors:405:5)
17:59:05.576 | web:build:     at validateString (node:internal/validators:162:11)
17:59:05.576 | web:build:     at Object.dirname (node:path:1275:5)
17:59:05.576 | web:build:     at 765218 (/vercel/path0/apps/web/.next/server/chunks/1074.js:156:349959)
17:59:05.576 | web:build:     at t (/vercel/path0/apps/web/.next/server/webpack-runtime.js:1:479)
17:59:05.576 | web:build:     at 841124 (/vercel/path0/apps/web/.next/server/chunks/1074.js:156:345522)
17:59:05.576 | web:build:     at t (/vercel/path0/apps/web/.next/server/webpack-runtime.js:1:479)
17:59:05.576 | web:build:     at 530195 (/vercel/path0/apps/web/.next/server/chunks/1074.js:156:342144)
17:59:05.576 | web:build:     at t (/vercel/path0/apps/web/.next/server/webpack-runtime.js:1:479)
17:59:05.576 | web:build:     at 853099 (/vercel/path0/apps/web/.next/server/chunks/1074.js:6:14349) {
17:59:05.577 | web:build:   code: 'ERR_INVALID_ARG_TYPE'
17:59:05.577 | web:build: }

web:build: Error occurred prerendering page "/_not-found". Read more: https://nextjs.org/docs/messages/prerender-error
web:build: 
web:build: TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string. Received type number (96184)
web:build:     at new NodeError (node:internal/errors:405:5)
web:build:     at validateString (node:internal/validators:162:11)
web:build:     at Object.dirname (node:path:1275:5)
web:build:     at 765218 (/vercel/path0/apps/web/.next/server/chunks/1074.js:156:349959)
web:build:     at t (/vercel/path0/apps/web/.next/server/webpack-runtime.js:1:479)
web:build:     at 841124 (/vercel/path0/apps/web/.next/server/chunks/1074.js:156:345522)
web:build:     at t (/vercel/path0/apps/web/.next/server/webpack-runtime.js:1:479)
web:build:     at 530195 (/vercel/path0/apps/web/.next/server/chunks/1074.js:156:342144)
web:build:     at t (/vercel/path0/apps/web/.next/server/webpack-runtime.js:1:479)
web:build:     at 853099 (/vercel/path0/apps/web/.next/server/chunks/1074.js:6:14349)

TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string. Received type number (96184)
--
17:59:08.346 | web:build:     at new NodeError (node:internal/errors:405:5)
17:59:08.346 | web:build:     at validateString (node:internal/validators:162:11)
17:59:08.346 | web:build:     at Object.dirname (node:path:1275:5)
17:59:08.346 | web:build:     at 765218 (/vercel/path0/apps/web/.next/server/chunks/1074.js:156:349959)
17:59:08.346 | web:build:     at t (/vercel/path0/apps/web/.next/server/webpack-runtime.js:1:479)
17:59:08.346 | web:build:     at 841124 (/vercel/path0/apps/web/.next/server/chunks/1074.js:156:345522)
17:59:08.346 | web:build:     at t (/vercel/path0/apps/web/.next/server/webpack-runtime.js:1:479)
17:59:08.346 | web:build:     at 530195 (/vercel/path0/apps/web/.next/server/chunks/1074.js:156:342144)
17:59:08.346 | web:build:     at t (/vercel/path0/apps/web/.next/server/webpack-runtime.js:1:479)
17:59:08.346 | web:build:     at 853099 (/vercel/path0/apps/web/.next/server/chunks/1074.js:6:14349) {
17:59:08.346 | web:build:   code: 'ERR_INVALID_ARG_TYPE'
17:59:08.346 | web:build: }

web:build: Error occurred prerendering page "/create-squad". Read more: https://nextjs.org/docs/messages/prerender-error
--
17:59:08.346 | web:build:
17:59:08.346 | web:build: TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string. Received type number (96184)
17:59:08.346 | web:build:     at new NodeError (node:internal/errors:405:5)
17:59:08.346 | web:build:     at validateString (node:internal/validators:162:11)
17:59:08.347 | web:build:     at Object.dirname (node:path:1275:5)
17:59:08.347 | web:build:     at 765218 (/vercel/path0/apps/web/.next/server/chunks/1074.js:156:349959)
17:59:08.347 | web:build:     at t (/vercel/path0/apps/web/.next/server/webpack-runtime.js:1:479)
17:59:08.347 | web:build:     at 841124 (/vercel/path0/apps/web/.next/server/chunks/1074.js:156:345522)
17:59:08.347 | web:build:     at t (/vercel/path0/apps/web/.next/server/webpack-runtime.js:1:479)
17:59:08.347 | web:build:     at 530195 (/vercel/path0/apps/web/.next/server/chunks/1074.js:156:342144)
17:59:08.347 | web:build:     at t (/vercel/path0/apps/web/.next/server/webpack-runtime.js:1:479)
17:59:08.347 | web:build:     at 853099 (/vercel/path0/apps/web/.next/server/chunks/1074.js:6:14349)
17:59:08.347 | web:build:     Generating static pages (2/6)
17:59:08.347 | web:build:     Generating static pages (4/6)

web:build: > Export encountered errors on following paths:
web:build:  /_not-found
web:build:  /create-squad/page: /create-squad
web:build:  /squads/page: /squad
lforst commented 1 month ago

Hi, can you try and make out from the stack trace and maybe with source map where this error comes from? A way to reproduce this somehow would also be awesome! Thanks!

Palmaswell commented 1 month ago

Hi @lforst, thanks so much for you prompt reply.

I tried vizualizing the stack trace for the TypeError [ERR_INVALID_ARG_TYPE] error. As you can see in the images below the error orginates in the @opentelemetry/instrumentation/build/esm/instrumentation.js in the runSpanCustomizationHook and ends in Node's resolve/lib/core as effectively shown in the source map vizualization it receives path.dirname(96184). I hope this can help us get any further.

Below the images from top to bottom like in the stack trace:

at 765218 (/Users/mau/Repos/Squads/squads/apps/web/.next/server/chunks/3426.js:157:349959) Screenshot 2024-06-10 at 13 01 04

at 841124 (/Users/mau/Repos/Squads/squads/apps/web/.next/server/chunks/3426.js:157:345522) Screenshot 2024-06-10 at 13 00 28

at 530195 (/Users/mau/Repos/Squads/squads/apps/web/.next/server/chunks/3426.js:157:342144) Screenshot 2024-06-10 at 13 00 02

at 110401 (/Users/mau/Repos/Squads/squads/apps/web/.next/server/chunks/3426.js:6:14780

Screenshot 2024-06-10 at 12 58 36

Please let me know anything else I can do to solve the issue.

lforst commented 1 month ago

Thanks a bunch for providing the resolved code! I think all frames except for the top one resolved weirdly though. I don't have a solution to this yet but this seems like a buggy mixture of opentelemetry/webpack to me. Webpack seems to be turning require.resolve('is-core-module/package.json') into 96184.

Do you have any other plugins/configurations that may influence module resolution? Maybe something like a json file resolver?

Palmaswell commented 1 month ago

Please take a look at our Next.js config below. The only thing I can think about is the config resolve fallback we currently require for an NPM module.

import { withSentryConfig } from "@sentry/nextjs";
import { createVanillaExtractPlugin } from "@vanilla-extract/next-plugin";

const withVanillaExtract = createVanillaExtractPlugin({
  outputCss: true,
});

/** @type {import('next').NextConfig} */
const nextConfig = {
  reactStrictMode: true,
  transpilePackages: ["@squads/ui"],
  experimental: {
    instrumentationHook: true,
    serverComponentsExternalPackages: ["@sentry/profiling-node"],
  },
  images: {
    remotePatterns: [
      {
        protocol: "https",
        hostname: "**",
      },
    ],
  },
  redirects: async () => {
    return [{ source: "/", destination: "/squads", permanent: true }];
  },
  webpack: (config, { nextRuntime, isServer }) => {
    if (nextRuntime === "edge") {
      // This is equivalent to { fallback: {"node:crypto": false} }
      config.externals.push({
        "node:crypto": "{}",
        stream: "{}",
      });
    }

    config.externals.push({
      "@sentry/profiling-node": "commonjs @sentry/profiling-node",
    });

    if (!isServer) {
      config.resolve.fallback = {
        ...config.resolve.fallback,
        fs: false,
      };
    }
    return config;
  },
};

export default withSentryConfig(
  withVanillaExtract(nextConfig),
  { authToken: process.env.SENTRY_AUTH_TOKEN, silent: true },
  { hideSourceMaps: true }
);
Lms24 commented 1 month ago

Hey @Palmaswell, unfortunately our NextJS experts are out for a couple of days but we'll take another detailed look on Monday (cc @lforst and @s1gr1d and sorry for the ping 😬).

Just an observation: Looks like you added the third parameter to withSentryConfig again which won't have an effect for v8. You should move the option to the 2nd parameter although this probably won't fix the issue.

lforst commented 1 month ago

I honestly don't know what is going on here. Would you mind sharing a reproduction example? Something feels off, considering the source maps are also broken.

Palmaswell commented 4 weeks ago

Hi @lforst, what do you mean by a reproduction example? I would appreciate it if you could be more specific. Thanks again.

lforst commented 4 weeks ago

@Palmaswell Ideally something like a Repo we can pull or a Stackblitz where we can reproduce this error with clear instructions.

Palmaswell commented 3 weeks ago

Unfortunately, I can't share the repo as it's private for the organization I work for. I will prepare a reproduction on Stackblitz in the next couple of days.

cvoege commented 1 week ago

@Palmaswell did y'all ever figure out a fix for this? I'm having this on a brand new repo.

lforst commented 6 days ago

@cvoege would you mind sharing something we can use to reproduce locally?

Palmaswell commented 6 days ago

@Palmaswell did y'all ever figure out a fix for this? I'm having this on a brand new repo.

No, we were not able to fix this yet. It would be really great if you could share the team so they can reproduce.