node.jsnpmnode-modulesnpm-installnpm-update

NPM crashes when I try to update a package with --depth 21


I'm trying to fix the npm vulnerabilities in my project. On trying npm audit I got a command to fix the vulnerability in one of the packages. $ npm update kind-of --depth 21

On running this command, I'm getting the following message:

<--- Last few GCs --->
[27677:0x43e27b0]   655989 ms: Mark-sweep 1092.0 (1432.7) -> 1092.0 (1425.7) MB, 1401.7 / 0.0 ms  (average mu = 0.031, current mu = 0.007) last resort GC in old space requested
[27677:0x43e27b0]   657562 ms: Mark-sweep 1092.0 (1425.7) -> 1092.0 (1425.7) MB, 1573.0 / 0.0 ms  (average mu = 0.016, current mu = 0.000) last resort GC in old space requested
<--- JS stacktrace --->
==== JS stack trace =========================================
    0: ExitFrame [pc: 0x6d8f26dbe1d]
Security context: 0x3d028b51e6e1 <JSObject>
    1: isExtraneous(aka isExtraneous) [0x21dd9bc867d1] [/home/qburst/.nvm/versions/node/v10.13.0/lib/node_modules/npm/lib/install/is-extraneous.js:~4] [pc=0x6d8f2f64036](this=0x36cf643826f1 <undefined>,tree=0x0ca9a56e2291 <Node map = 0x391751aadd89>)
    2: /* anonymous */ [0x219a048fa6f9] [/home/qburst/.nvm/versions/node/v10.13.0/lib/node_modules/npm/lib/out...
FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory
 1: 0x8daaa0 node::Abort() [npm]
 2: 0x8daaec  [npm]
 3: 0xad73ce v8::Utils::ReportOOMFailure(v8::internal::Isolate*, char const*, bool) [npm]
 4: 0xad7604 v8::internal::V8::FatalProcessOutOfMemory(v8::internal::Isolate*, char const*, bool) [npm]
 5: 0xec4c32  [npm]
 6: 0xed444f v8::internal::Heap::AllocateRawWithRetryOrFail(int, v8::internal::AllocationSpace, v8::internal::AllocationAlignment) [npm]
 7: 0xea21e8 v8::internal::Factory::NewTransitionArray(int, int) [npm]
 8: 0x11db913 v8::internal::TransitionsAccessor::Insert(v8::internal::Handle<v8::internal::Name>, v8::internal::Handle<v8::internal::Map>, v8::internal::SimpleTransitionFlag) [npm]
 9: 0xfcb9b6 v8::internal::Map::ConnectTransition(v8::internal::Handle<v8::internal::Map>, v8::internal::Handle<v8::internal::Map>, v8::internal::Handle<v8::internal::Name>, v8::internal::SimpleTransitionFlag) [npm]
10: 0x1005d26 v8::internal::Map::CopyReplaceDescriptors(v8::internal::Handle<v8::internal::Map>, v8::internal::Handle<v8::internal::DescriptorArray>, v8::internal::Handle<v8::internal::LayoutDescriptor>, v8::internal::TransitionFlag, v8::internal::MaybeHandle<v8::internal::Name>, char const*, v8::internal::SimpleTransitionFlag) [npm]
11: 0x1007764 v8::internal::Map::CopyAddDescriptor(v8::internal::Handle<v8::internal::Map>, v8::internal::Descriptor*, v8::internal::TransitionFlag) [npm]
12: 0x1007943 v8::internal::Map::CopyWithField(v8::internal::Handle<v8::internal::Map>, v8::internal::Handle<v8::internal::Name>, v8::internal::Handle<v8::internal::FieldType>, v8::internal::PropertyAttributes, v8::internal::PropertyConstness, v8::internal::Representation, v8::internal::TransitionFlag) [npm]
13: 0x100cc55 v8::internal::Map::TransitionToDataProperty(v8::internal::Handle<v8::internal::Map>, v8::internal::Handle<v8::internal::Name>, v8::internal::Handle<v8::internal::Object>, v8::internal::PropertyAttributes, v8::internal::PropertyConstness, v8::internal::Object::StoreFromKeyed) [npm]
14: 0xfb35b8 v8::internal::LookupIterator::PrepareTransitionToDataProperty(v8::internal::Handle<v8::internal::JSReceiver>, v8::internal::Handle<v8::internal::Object>, v8::internal::PropertyAttributes, v8::internal::Object::StoreFromKeyed) [npm]
15: 0xff0109 v8::internal::Object::AddDataProperty(v8::internal::LookupIterator*, v8::internal::Handle<v8::internal::Object>, v8::internal::PropertyAttributes, v8::internal::ShouldThrow, v8::internal::Object::StoreFromKeyed) [npm]
16: 0x100ad7d v8::internal::Object::SetProperty(v8::internal::LookupIterator*, v8::internal::Handle<v8::internal::Object>, v8::internal::LanguageMode, v8::internal::Object::StoreFromKeyed) [npm]
17: 0x11654d5 v8::internal::Runtime::SetObjectProperty(v8::internal::Isolate*, v8::internal::Handle<v8::internal::Object>, v8::internal::Handle<v8::internal::Object>, v8::internal::Handle<v8::internal::Object>, v8::internal::LanguageMode) [npm]
18: 0x1166630 v8::internal::Runtime_SetProperty(int, v8::internal::Object**, v8::internal::Isolate*) [npm]
19: 0x6d8f26dbe1d 
[1]    27677 abort (core dumped)  npm update kind-of --depth 21

Could someone help me with this issue? Thank you.


Solution

  • I had encountered the same error and from looking at the error my intuition is that npm update at that depth of dependency tree is not feasible with our default resource settings of Node.js. (I confess that I have not researched more on this)

    Assuming I am close to truth in my above deduction, I do not recommend increasing any such default resource limits unless we know for sure what values are safe and good. Also because this issue happened only for a corner case while using npm.

    I see that you were trying to forcefully update kind-of at a certain level of dependency tree by running:

    npm update kind-of --depth 21
    

    However, since kind-of is a very widely used package, I suggest that you check all other levels of dependency tree (npm ls kind-of) and make sure if fixing kind-of's version only at depth 21 will make your npm audit clean.

    Solution (workaround)

    Use npm-force-resolutions. Quoting from the package's description:

    This packages modifies package-lock.json to force the installation of specific version of a transitive dependency (dependency of dependency), similar to yarn's selective dependency resolutions, but without having to migrate to yarn.

    Before you use it, let me also warn you

    The use case for this is when there is a security vulnerability and you MUST update a nested dependency otherwise your project would be vulnerable. But this should only be used as a last resource, you should first update your top-level dependencies and file an issue for them to update the vulnerable sub-dependencies (npm ls can help you with that).

    In your package.json, you just need to add a preinstall script

    "scripts": {
        "preinstall": "npx npm-force-resolutions"
    }
    

    and a directive field

    "resolutions": {
        "kind-of": ">=6.0.3"
    }
    

    (assuming you want to fix kind-of version to get rid of CVE-2019-20149)