Components.js icon indicating copy to clipboard operation
Components.js copied to clipboard

FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory

Open thhck opened this issue 10 months ago • 8 comments

Issue type:

  • :bug: Bug

Description:

When running npm run build on CSS the process get stuck at [Components.js] info: Generating components for 1 package and then return FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory


Environment:

Crash log:

<--- Last few GCs --->

[60020:0x6950420]   164556 ms: Scavenge 2023.6 (2079.2) -> 2016.6 (2080.0) MB, 5.4 / 0.0 ms  (average mu = 0.672, current mu = 0.438) allocation failure;
[60020:0x6950420]   164589 ms: Scavenge 2023.9 (2080.0) -> 2016.9 (2080.0) MB, 5.0 / 0.0 ms  (average mu = 0.672, current mu = 0.438) allocation failure;
[60020:0x6950420]   164625 ms: Scavenge 2024.4 (2080.0) -> 2017.3 (2096.5) MB, 6.3 / 0.0 ms  (average mu = 0.672, current mu = 0.438) allocation failure;


<--- JS stacktrace --->

FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory
 1: 0xb7a940 node::Abort() [node]
 2: 0xa8e823  [node]
 3: 0xd5c990 v8::Utils::ReportOOMFailure(v8::internal::Isolate*, char
const*, bool) [node]
 4: 0xd5cd37 v8::internal::V8::FatalProcessOutOfMemory(v8::internal::Isolate*, char const*, bool) [node]
 5: 0xf3a435  [node]
 6: 0xf4c91d v8::internal::Heap::CollectGarbage(v8::internal::AllocationSpace, v8::internal::GarbageCollectionReason, v8::GCCallbackFlags) [node]
 7: 0xf2701e v8::internal::HeapAllocator::AllocateRawWithLightRetrySlowPath(int, v8::internal::AllocationType, v8::internal::AllocationOrigin, v8::internal::AllocationAlignment) [node]
 8: 0xf283e7 v8::internal::HeapAllocator::AllocateRawWithRetryOrFailSlowPath(int, v8::internal::AllocationType, v8::internal::AllocationOrigin, v8::internal::AllocationAlignment) [node]
 9: 0xf095ba v8::internal::Factory::NewFillerObject(int, v8::internal::AllocationAlignment, v8::internal::AllocationType, v8::internal::AllocationOrigin) [node]
10: 0x12ce7ff v8::internal::Runtime_AllocateInYoungGeneration(int, unsigned long*, v8::internal::Isolate*) [node]
11: 0x16fb6f9  [node]
^C

thhck avatar Feb 12 '25 16:02 thhck

I suspect @joachimvh will be able to help better than myself on this one.

rubensworks avatar Feb 12 '25 16:02 rubensworks

Is it possible to create infinite loop with a bad configuration ?

it seems like one.

thhck avatar Feb 12 '25 17:02 thhck

Ok I have found the root of the issue comes from a dependency that should be overrided but it is not. will report back when I have more

thhck avatar Feb 12 '25 17:02 thhck

So:

in config/foo.json

  {
      "@id": "urn:Foo",
      "@type": "Foo",
      "secret": "this parameter will be overrided by main_config.json."
    },

in config/bar.json

{
        "@id": "urn:Bar",
        "@type": "Bar",
        "foo": {"@id": "urn:Foo"}
      }

in main_config.json

{
  "@context": [...],
  "import": [
    "foobar:config/foo.json",
    "foobar:config/bar.json"
  ],
  "@graph": [
    {
      "@id": "urn:FooOverride",
      "@type": "Override",
      "overrideInstance": { "@id": "urn:Foo" },
      "overrideParameters": {
        "@type": "Foo",
        "secret": "s3cr3t_p4ssw0rd",
      }
    }
  ]
}

I think that is, in a nutshell , the issue:

Bar is using Foo as a dependency, but it take the one that is not overridden, so it has the wrong secret argument, which might create the infinity loop.

thhck avatar Feb 12 '25 18:02 thhck

I have created a minimal repo based on your examples at https://github.com/joachimvh/components-heap-error

When running bin/run.js it prints s3cr3t_p4ssw0rd as the value received for both classes and there is no crash. Does this match what you mean or is something missing?

joachimvh avatar Feb 14 '25 09:02 joachimvh

Thanks @joachimvh for doing this MRE

And indeed I was mistaken, this was not the cause of the infinity loop.

I have found the cause of issue, It was importing Foo in Bar.ts with :

import { Foo } from './index'

instead of

import { Foo } from './Foo'

Using codium, when I first write the logic and then the imports. So in the this MRE if I just type :

export class Bar {
  public constructor(
    public foo: Foo,
  ) {
    console.log('Bar', foo.secret);
  }
}

codium underline Foo in red and if I right-click on it, the "Quick Fix" give the option to import Foo from ./index or from ./Foo.

However in the original code (which has a more complex structure) I pretty sure codium automatically wrote the import for me from ./index, without me noticing.

thhck avatar Feb 14 '25 15:02 thhck

I can confirm that there is an issue when trying to build the components, so this is already an issue with the generator and has nothing to do with the overrides.

@rubensworks is it a known issue that the generator gets into trouble if you import from the index instead of the file directly?

joachimvh avatar Feb 18 '25 08:02 joachimvh

is it a known issue that the generator gets into trouble if you import from the index instead of the file directly?

No, I believe I'm even doing this as well in some of my projects.

Maybe there's a cycle in the imports somehow? Even though I thought we had safety checks for that...

rubensworks avatar Feb 18 '25 08:02 rubensworks