getsentry / sentry-javascript

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

Out of memory when building NextJS application with sentry #13836

Open ricardomatias opened 5 days ago

ricardomatias commented 5 days ago

Environment

SaaS (https://sentry.io/)

Steps to Reproduce

npx @sentry/wizard@latest -i nextjs

All options for enhancements were marked as off.

Expected Result

That I can build the NextJS application. This is happening in a VPS from Hetzner with 4 vCPUs and 8gb ram.

Actual Result

> build
> next build

  ▲ Next.js 14.2.12
  - Environments: .env.production
  - Experiments (use with caution):
    · instrumentationHook

   Creating an optimized production build ...

<--- Last few GCs --->

[25731:0x5d24710]    90147 ms: Scavenge (reduce) 2040.5 (2073.9) -> 2039.8 (2074.1) MB, 2.69 / 0.00 ms  (average mu = 0.125, current mu = 0.002) allocation failure;
[25731:0x5d24710]    91060 ms: Mark-Compact (reduce) 2040.6 (2074.1) -> 2040.0 (2074.4) MB, 911.94 / 0.00 ms  (average mu = 0.090, current mu = 0.055) allocation failure; scavenge might not succeed

<--- JS stacktrace --->

FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory
----- Native stack trace -----

 1: 0xb82d33 node::OOMErrorHandler(char const*, v8::OOMDetails const&) [node]
 2: 0xef0c50 v8::Utils::ReportOOMFailure(v8::internal::Isolate*, char const*, v8::OOMDetails const&) [node]
 3: 0xef0f37 v8::internal::V8::FatalProcessOutOfMemory(v8::internal::Isolate*, char const*, v8::OOMDetails const&) [node]
 4: 0x1102ad5  [node]
 5: 0x1103064 v8::internal::Heap::RecomputeLimits(v8::internal::GarbageCollector) [node]
 6: 0x1119f54 v8::internal::Heap::PerformGarbageCollection(v8::internal::GarbageCollector, v8::internal::GarbageCollectionReason, char const*) [node]
 7: 0x111a76c v8::internal::Heap::CollectGarbage(v8::internal::AllocationSpace, v8::internal::GarbageCollectionReason, v8::GCCallbackFlags) [node]
 8: 0x10f0a71 v8::internal::HeapAllocator::AllocateRawWithLightRetrySlowPath(int, v8::internal::AllocationType, v8::internal::AllocationOrigin, v8::internal::AllocationAlignment) [node]
 9: 0x10f1c05 v8::internal::HeapAllocator::AllocateRawWithRetryOrFailSlowPath(int, v8::internal::AllocationType, v8::internal::AllocationOrigin, v8::internal::AllocationAlignment) [node]
10: 0x10cf256 v8::internal::Factory::NewFillerObject(int, v8::internal::AllocationAlignment, v8::internal::AllocationType, v8::internal::AllocationOrigin) [node]
11: 0x152b086 v8::internal::Runtime_AllocateInYoungGeneration(int, unsigned long*, v8::internal::Isolate*) [node]
12: 0x7d341bcd9ef6
Aborted (core dumped)

Product Area

Unknown

Link

No response

DSN

No response

Version

No response

getsantry[bot] commented 5 days ago

Assigning to @getsentry/support for routing ⏲️

chargome commented 4 days ago

Hi @ricardomatias, does the build succeed locally without problems? Could you paste your next config here?

ricardomatias commented 4 days ago

The issue in the context that I created is still there, but I've managed to get to a stage where I can build the application (albeit it's very slow). I recall disabling sourcemaps was the first change which resulted in a successful build. Now it works even with sourcemaps, but I cant recall all the steps I took during that journey. This is my next config at the moment, which works:

const nextConfig = {
    webpack: (config, options) => {
        config.module.rules.push({
            test: /\.html/,
            use: [
                options.defaultLoaders.babel,
                {
                    loader: 'html-loader',
                },
            ],
        })

        return config
    },
    experimental: {
        instrumentationHook: true,
        serverActions: {
            bodySizeLimit: '10mb',
        },
    },

};

export default withSentryConfig(withNextIntl(nextConfig), {
    // For all available options, see:
    // https://github.com/getsentry/sentry-webpack-plugin#options

    org: "XXXX",
    project: "XXXX",
    telemetry: false,

    // Only print logs for uploading source maps in CI
    silent: false,

    // For all available options, see:
    // https://docs.sentry.io/platforms/javascript/guides/nextjs/manual-setup/

    // Upload a larger set of source maps for prettier stack traces (increases build time)
    widenClientFileUpload: false,

    // Route browser requests to Sentry through a Next.js rewrite to circumvent ad-blockers.
    // This can increase your server load as well as your hosting bill.
    // Note: Check that the configured route will not match with your Next.js middleware, otherwise reporting of client-
    // side errors will fail.
    tunnelRoute: "/monitoring",
    sourcemaps: {
        disable: true
    },

    // Hides source maps from generated client bundles
    hideSourceMaps: true,

    // Automatically tree-shake Sentry logger statements to reduce bundle size
    disableLogger: true,

    // Enables automatic instrumentation of Vercel Cron Monitors. (Does not yet work with App Router route handlers.)
    // See the following for more information:
    // https://docs.sentry.io/product/crons/
    // https://vercel.com/docs/cron-jobs
    automaticVercelMonitors: false,
});
lforst commented 4 days ago

From what I've seen other users report is that memory consumption with sourcemaps enabled always seems to hover around 4GB, it could be that you get lucky with some builds even when sourcemaps are enabled.

m-sanders commented 3 days ago

Try setting NODE_OPTIONS=--max-old-space-size=SIZE to something >2GB. The recommendation is 75% of the available space NODE_OPTIONS=--max-old-space-size=6144. Node will not use most of your 8GB of heap without this. As you can see in the logs, it ran out of memory with around 2GB of memory.

Additionally, you may find that setting an explicit experimental.cpus might help: https://github.com/vercel/next.js/issues/48352 I have seen next build with 32 CPUs crash as it creates 32 workers that eat up all the memory and crash. Setting to 4 CPUs resolved this build issue for me; maybe setting it to 1 or 2 might help. But I would start with increasing the old space size first.

As an aside: you will likely benefit from setting --max-semi-space-size= to something greater than the default 8/16mb (I have found 64mb) helps to reduce garbage collection pauses greatly but this is outside of the scope of your problem and something to experiment with.

lforst commented 3 days ago

@m-sanders that is some great input. Thank you very much!