Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TypeError: Cannot read property 'name' of undefined using log4js (^6.4.0) with angular in ssr mode #1225

Closed
myuniverse8 opened this issue Apr 1, 2022 · 14 comments · Fixed by log4js-node/streamroller#116, #1232 or log4js-node/streamroller#119
Labels
dependencies Pull requests that update a dependency file
Milestone

Comments

@myuniverse8
Copy link

Hello,

I am facing one issue in chain of packages: "log4js" -> "streamroller" -> "fs-extra" -> "graceful-fs" and "universalify"

This is the way how it could be reproduced:

  1. Create a new angular project
  2. Implement ssr (https://angular.io/guide/universal)
  3. Install "log4js" and use it to log something in server.ts file for example:

image

  1. Build and run this project in ssr mode.

The error will be in terminal:
image

After some investigations I have found that in last versions of "log4js" the version of "streamroller" was changed from "2.x.x" to "3.x.x" which caused changing the version of "fs-extra" to the last one.

The issue occurs in "universalify" package which is used by "fs-extra":
image

If we go step up in the callstack then we see this part of code in "fs-extra":
image

Previously it has a verification that prevented this issue:
image

But it was changed in this commit jprichardson/node-fs-extra@f4a880d:

In this case maybe "graceful-fs" should be updated in order to return proper value in this case, because it doesn't return proper value for fs.realpath.native:
image

With "log4js" version 6.3.0 there is no such issue because it uses the old version of "streamroller" which uses the old version of "fs-extra" which has versification mentioned above.

I am not sure on which package I should report this issue but I see it because I am using "log4js" so maybe this is the right place to start.

Could you please check it?

Thank you very much for your help in advance.

Best Regards,
Andrei

@myuniverse8
Copy link
Author

myuniverse8 commented Apr 1, 2022

Angular: 12.2.16
Angular CLI: 12.2.16
Node: 14.18.1
Package Manager: npm 6.14.15
Log4js: 6.4.4

@lamweili
Copy link
Contributor

lamweili commented Apr 5, 2022

Seems similar to #1186 (comment).

The error is thrown during the import of log4js as mentioned in another comment, #1186 (comment).

The verification by fs-extra was removed to do away with the redundant checks, since fs-realpath.native is de-facto included since NodeJS 9.2.0.
(src: jprichardson/node-fs-extra#887)

NodeJS 14.18.1 should have fs.realpath.native.

It does seem like graceful-fs wasn't able to load and use the fs.realpath.native from NodeJS, since graceful-fs merely extends/override on existing functions.

@lamweili
Copy link
Contributor

lamweili commented Apr 6, 2022

I have some findings:

  1. Using the ready-made https://angular.io/generated/zips/universal/universal.zip from https://angular.io/guide/universal.

  2. Edited server.ts or the TypeScript would whine (TS4111) and refuse to run.

    -  const port = process.env.PORT || 4000;
    +  const port = process.env['PORT'] || 4000;
  3. I added the following at the very beginning of the server.ts:

    +  console.log("NODEJS VERSION:", process.version);
    
    +  console.log("=====1=====");
    +  import * as fs from 'fs';
    +  console.log("2nd-level API fs.appendFile:", fs.appendFile); // a second-level API (fs.xxx)
    +  console.log("2nd-level API fs.realpath:", fs.realpath);
    +  console.log("3rd-level API fs.realpath.native:", fs.realpath.native); // a third-level API (fs.xxx.yyy)
    
    =  import 'zone.js/node';
    
    +  console.log("=====2=====");
    +  console.log("2nd-level API fs.appendFile:", fs.appendFile); // a second-level API (fs.xxx)
    +  console.log("2nd-level API fs.realpath:", fs.realpath);
    +  console.log("3rd-level API fs.realpath.native:", fs.realpath.native); // a third-level API (fs.xxx.yyy)
    
    =  import { ngExpressEngine } from '@nguniversal/express-engine';
  4. npm install followed by npm run dev:ssr command.

  5. It seems like the import 'zone.js/node'; did something to the fs.
    fs.realpath.native become undefined from the logs.

    image

  6. It does seem like zone.js/node did not factor in fs third-level functions. From the fs API documentation, most are second-level functions (i.e. fs.xxx). But there are 2 exceptions since NodeJS 9.2.0 that are in third-level (i.e. fs.xxx.yyy), which are fs.realpath.native and fs.realpathSync.native. So when the package did some wrapping around, the third-level functions broke.

@lamweili
Copy link
Contributor

lamweili commented Apr 6, 2022

@myuniverse8, I'm not sure how we can move ahead.

My gut feel is zone.js/node (which is https://github.com/angular/angular/tree/master/packages/zone.js). Yet fs-extra should have some form of defensive coding.


Perhaps you can try filing an issue with zone.js/node?
It does seem like their issue, and you have a solid case, especially by using their examples and the results from #1225 (comment).


Alternatively, while technically it's not their issue, you can try filing an issue with fs-extra with the findings in the hopes that they can consider re-adding the checks to have some form of defensive-coding as I doubt only Angular is affected. There should be more collateral damage somewhat.

@lamweili
Copy link
Contributor

lamweili commented Apr 6, 2022

@myuniverse8
Copy link
Author

myuniverse8 commented Apr 6, 2022

Hi, @peteriman, thank you very much for your investigation and your help! I will check both issues/PRs.

@lamweili lamweili added the dependencies Pull requests that update a dependency file label Apr 6, 2022
@zhaosheng808
Copy link

I have the same problem in Node v8.11.3,
but it works well in Node v12.13.1;
What do I need to do to make it work well without upgrading Node version?

Node: 8.11.3
Log4js: 6.4.4

@lamweili
Copy link
Contributor

lamweili commented Apr 7, 2022

@zhaosheng808, fs.realpath.native is only available from NodeJS 9.2.0 onwards.
That explains why NodeJS 8.11.3 doesn't work yet NodeJS 12.13.1 works.


The dependency chain is log4js@^6.4.0 > streamroller@^3.0.1 > fs-extra@^10.0.1 > graceful-fs & universalify.

fs-extra removed the check for fs.realpath.native in jprichardson/node-fs-extra@f4a880d (or jprichardson/node-fs-extra#887) which is released in fs-extra@10.0.0 (but not listed changelog).

Without the check, it assumes fs.realpath.native exists. And if it is undefined, it fails on import/require initialisation at fs-extra, when it tries to universalify the undefined.


  1. For your case, I would recommend upgrading your NodeJS, since the minimum NodeJS in LTS is now NodeJS 12. If you don't want that much of a major leap, perhaps minimally upgrade to NodeJS 10.

  2. If you are unable to upgrade, perhaps you can head over to Revert check for fs.realpath.native (#887) jprichardson/node-fs-extra#953 and convince them to revert the checks for compatibility reasons.

  3. As a very last resort (and an extremely terrible practice), you can monkey-patch your legacy NodeJS 8 so that your fs.realpath.native is not undefined. Something along the lines of fs.realpath.native = fs.realpath; (at least the method/parameter definition is the same to mitigate any possible regression, refer to below) at the very start of your application, before you import/require log4js or any dependencies that use fs-extra@^10.0.0.

@zhaosheng808
Copy link

Hi, @peteriman , I've upgraded NodeJS to v12. Now it can be used normally. thank you very much~

@lamweili
Copy link
Contributor

lamweili commented Apr 8, 2022

@zhaosheng808, you are welcome.
Your case (different from @myuniverse8) is pretty straightforward.

I'm glad you got it resolved. 🤗

@lamweili
Copy link
Contributor

lamweili commented Apr 15, 2022

Instead of waiting for the next release fs-extra, I took the liberty to defensively patch it in streamroller.
This is an interim measure so that log4js can be imported without errors from its nested dependencies.

Currently, if fs.realpath.native is undefined, the import of log4js will fail because:

  • caused by import of log4js throwing error (from streamroller/fs-extra)
  • caused by import of streamroller throwing error (from fs-extra)
  • caused by import of fs-extra throwing error
  • caused by fs.realpath.native being undefined

Once fs-extra has released the fixes, I will upgrade it and revert the defensive patch in streamroller.

Fixed in streamroller@3.0.7 - changelog.
Fixed in log4js@6.4.5 (which has dependency bumped to streamroller@3.0.7).

@myuniverse8 Please try it out and get back to me. Thanks!

@myuniverse8
Copy link
Author

@peteriman it works for me now. Thank you and your colleagues very much for your support and the quick fix!

@lamweili
Copy link
Contributor

lamweili commented Apr 17, 2022

Just an update, it has been defensively patched in jprichardson/node-fs-extra#953 and released in fs-extra@10.1.0.

But still, why is fs.realpath.native undefined? That is still a root cause by Angular SSR angular/angular#45546.

In the next version of streamroller, the interim defensive patch will be removed and fs-extra upgraded.

@lamweili
Copy link
Contributor

Reverted the interim patch in streamroller@3.0.7 as it has been patched in fs-extra@10.1.0.

Released streamroller@3.0.8 with upgraded fs-extra@10.1.0 - changelog.
Released log4js@6.4.6 (which has dependency bumped to streamroller@3.0.8).

@lamweili lamweili changed the title TypeError: Cannot read property 'name' of undefined using last version of log4js (6.4.4) with angular in ssr mode TypeError: Cannot read property 'name' of undefined using log4js (^6.4.0) with angular in ssr mode Apr 26, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
dependencies Pull requests that update a dependency file
Projects
None yet
3 participants