auth-module: Javascript heap out of memory

Version

v4.5.0

Reproduction link

https://github.com/cannap/nuxt-memory-leak in this repo i use nuxt-edge i also havew the same issue with stable nuxt

Steps to reproduce

  1. Create Express app via npx create…
  2. Install nuxtjs/auth
  3. Add auth module to the modules in nuxt.config ( thats the only thing i changed )

What is expected ?

It should work?

What is actually happening?

<--- Last few GCs --->

[22956:0000020E759F3800]    31715 ms: Mark-sweep 1349.2 (1456.5) -> 1349.0 (1456.5) MB, 665.2 / 0.4 ms  (average mu = 0.112, current mu = 0.002) allocation failure GC in old space requested
[22956:0000020E759F3800]    32372 ms: Mark-sweep 1349.0 (1456.5) -> 1349.0 (1456.5) MB, 657.0 / 0.4 ms  (average mu = 0.057, current mu = 0.001) allocation failure GC in old space requested


<--- JS stacktrace --->

==== JS stack trace =========================================

    0: ExitFrame [pc: 00000151DE6841C1]
Security context: 000000C44689E589 <JSObject>
    1: _extend [00000296A6B8FFB9] [util.js:~1213] [pc=00000151DECB6B9B](this=00000296A6B8E789 <Object map = 0000006C38B303B1>,target=000002CA51EBAA19 <Object map = 0000006C38B023B9>,source=000003B1D83A13F9 <Object map = 000002FD31AD3719>)    2: new constructor(aka ClientRequest) [000003D1BB1B2F81] [_http_client.js:76] [bytecode=0000032A5B2FC3B1 offset=1...

FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory
 1: node::DecodeWrite
 2: node_module_register
 3: v8::internal::FatalProcessOutOfMemory
 4: v8::internal::FatalProcessOutOfMemory
 5: v8::internal::Heap::MaxHeapGrowingFactor
 6: v8::internal::ScavengeJob::operator=
 7: v8::internal::ScavengeJob::operator=
 8: v8::internal::ScavengeJob::operator=
 9: v8::internal::Heap::MaxHeapGrowingFactor
10: v8::internal::Factory::AllocateRawArray
11: v8::internal::Factory::NewFixedArrayWithFiller
12: v8::internal::Literal::ToBooleanIsTrue
13: v8::internal::Literal::ToBooleanIsTrue
14: v8::internal::JSReceiver::GetOwnPropertyDescriptor
15: v8::internal::JSReceiver::GetOwnPropertyDescriptor
16: v8::internal::JSReceiver::GetOwnPropertyDescriptor
17: v8::internal::JSReceiver::class_name
18: v8::internal::JSReceiver::GetOwnPropertyDescriptor
19: v8::internal::LookupIterator::PrepareTransitionToDataProperty
20: v8::internal::JSReceiver::class_name
21: v8::internal::interpreter::BytecodeDecoder::Decode
22: v8::internal::interpreter::BytecodeDecoder::Decode
23: 00000151DE6841C1

Additional comments?

i also used the latest 4.5.3

node version: 10.4.1 Windows 10 64bit pro

Packages:

{
  "name": "yyyy",
  "version": "1.0.0",
  "description": "My pioneering Nuxt.js project",
  "author": "cannap",
  "private": true,
  "scripts": {
    "dev": "cross-env NODE_ENV=development  nodemon server/index.js --watch server",
    "build": "nuxt build",
    "start": "cross-env NODE_ENV=production node server/index.js",
    "generate": "nuxt generate",
    "lint": "eslint --ext .js,.vue --ignore-path .gitignore .",
    "precommit": "npm run lint"
  },
  "dependencies": {
    "@nuxtjs/auth": "^4.5.0",
    "@nuxtjs/axios": "^5.3.6",
    "body-parse": "^0.1.0",
    "cookie-parser": "^1.4.3",
    "cross-env": "^5.2.0",
    "csurf": "^1.9.0",
    "express": "^4.16.4",
    "express-async-errors": "^3.1.1",
    "nuxt": "^2.3.4"
  },
  "devDependencies": {
    "@vue/eslint-config-standard": "^4.0.0",
    "babel-eslint": "^10.0.1",
    "eslint": "^5.11.1",
    "eslint-config-prettier": "^3.3.0",
    "eslint-loader": "^2.1.1",
    "eslint-plugin-prettier": "3.0.1",
    "eslint-plugin-vue": "^5.0.0",
    "nodemon": "^1.18.9",
    "prettier": "1.15.3"
  }
}
<div align="right">This bug report is available on Nuxt community (#c255)</div>

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Reactions: 20
  • Comments: 40 (7 by maintainers)

Most upvoted comments

Hi. Sorry for the quick reply. The problem with this error is an axios misconfiguration. From the reproduction link:

  axios: {
    // See https://github.com/nuxt-community/axios-module#options
    baseURL: 'http://127.0.0.1:3000'
  }

This line is completely wrong. Because instructs axios to request to SSR server itself, which makes an infinite loop. (/api/auth)

I recommend either pointing baseURL to an external URL OR use proxy feature.

Again my apologies for lack of enough docs and enough info about error. Also nuxt should internally handle such error.

You neeed more ram

Get Outlook for iOShttps://aka.ms/o0ukef


From: Joel Hernández notifications@github.com Sent: Saturday, April 18, 2020 3:13:32 PM To: nuxt-community/auth-module auth-module@noreply.github.com Cc: Subscribed subscribed@noreply.github.com Subject: Re: [nuxt-community/auth-module] Javascript heap out of memory (#286)

Trying to spawn a fresh weekend project with Nuxt here and stumbling on this after running npx create-nuxt-app

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHubhttps://github.com/nuxt-community/auth-module/issues/286#issuecomment-615878433, or unsubscribehttps://github.com/notifications/unsubscribe-auth/ACUTT3KLNF7MKKFYF7ORHXDRNGYQZANCNFSM4GMPEFDA.

Hello everyone. I was chasing this one down all day today!

For anyone having this issue I’ve learned there is a default local authentication strategy which if not explicitly disabled will be the active default strategy due to the way options are overloaded onto Auth module defaults.

The best way to correct this is to explicitly set the “local” strategy to false in your strategies map.

You can confirm you are affected by this same issue by inspecting your nuxt server. node inspect server/index.js and then breaking after you trigger the infinite loop. You may have to try a few times but you might find Nuxt is trying to render in a new context through axios /api/auth/user which got me thinking, where do I have a strategy defined like that? The answer is that I don’t. Nuxt defined it, and it’s an undocumented default behavior.

Sure @pi0 's comment above will cover it up by forcing their “local” strategy to fail on first request but it’s better to turn off the rogue strategy altogether if you exclusively use Auth0 or some other service for authentication. Setting a baseURL to avoid the potential for infinite loops will be ideal though in relation to any other auth strategies using relative paths.

auth: {
    // Doc: https://auth.nuxtjs.org/getting-started/options
    redirect: {
      login: '/login',
      logout: '/',
      callback: '/login',
      home: '/'
    },
    strategies: {
      local: false,
      auth0: {
        domain: 'TENANT.auth0.com',
        client_id: 'CLIENT_ID'
      }
    }
  },

In my case, this is because nuxt.config.js does not have access to .env.

The solution was simple, but difficult to find due to the confusing documentation.

In the last lines of README.md in the module @nuxt/dotenv (https://github.com/nuxt-community/dotenv-module) it is explained how to use .env.

So it was enough to add this to nuxt.config.js

nuxt.config.js

require('dotenv').config()

No, I didn’t.

I changed the mode from universal to spa, ran it and this allowed me to see that there was a recursion error on Vue. Fixed it and everything works again.

Would be useful to have a descriptive error on this on universal mode.

@pi0 since I also face this issue and want to use local-scheme by default. Does not seem like a really strange behaviour to me. I understand that it might be technically complicated, but users’ desire is purely rational.

Are there any hacks to make it work? Proxies, client-side only requests, etc?

I had the same problem, except, I figured out that it was due to a component (ie, Footer.vue) that had the same component nested inside it’s self:

you can do it this was not the problem https://vuejs.org/v2/guide/components-edge-cases.html#Recursive-Components

and the problem was https://github.com/nuxt-community/auth-module/issues/286#issuecomment-461138282

I had similar problem just now also with using proxy module with pathRewrite: { '^/api/': '/' }.

That was the problematic line: user: { url: '/profile', method: 'get', propertyName: false } and the only thing that fixed it was adding /api prefix so url will be /api/profile so proxy could properly work.

As for me it should spit error and not make all the app crash altogether. I’m a bit scared to use it further to be honest.

No, I didn’t.

I changed the mode from universal to spa, ran it and this allowed me to see that there was a recursion error on Vue. Fixed it and everything works again.

Would be useful to have a descriptive error on this on universal mode.

Save my life, thx.

@pi0 The local strategy is useful as a default, but I think having to set local: false is fairly odd especially when following the Auth0 usage guide. What is even more strange to me is having to define every parameter within the local strategy to prevent the defaults from overloading where I’ve not defined something. e.g. I did not expect a logout call to be made when I failed to define logout: false on my own local strategy. The documentation even lists the default strategy as an “example” here which misleads the users even more.

Regarding redirect detection, I think SSR->SSR requests might still be useful or at least someone likely uses them out there. I tried looking up how Nginx or Apache manage to detect redirect loops but the internet is flooded with confused WordPress users. Perhaps such a solution could be baked into the Axios handler to detect infinite loops in the request chain capping at 10 requests deep before tossing an error.

Edit: Here is a particularly strange case of how the local strategy is confusing…it enforces a “user” property on the user info response forcing the definition of propertyName: false in order to get an OpenID Connect compliant response. My sane default would be to use the response as the user when a propertyName is not provided not to require this boilerplate.

 user: { url: '/userinfo', method: 'get', propertyName: false }

@sobolevn something I’m still thinking about is we can somehow prevent making SSR-SSR requests to prevent such loops and notify users that something is wrong. The proxy can still potentially make such loops.