Inversifyjs: "Cannot read 'name' of undefined" happens occasionally when incorrect import order

Created on 25 Nov 2018  路  3Comments  路  Source: inversify/InversifyJS


The issue is quite vague.
I am creating the project (code). It is a back-end, so I have an entry point to my server and a cli script that populates the database.
The problem is that my UserModel, that has a single dependency (a connection), can be container.get() from the CLI database script and fails when I try to start the server within the same project.
All annotations are set, 'reflect-metadata' is imported (even tried doing it several times :) ) and I see no differences between server and CLI scripts (regarding Inversify).

Expected Behavior



The UserModel instance can be acquired under any circumstances (see code).

Current Behavior



When I try to import from server scripts, I get Cannot read 'name' of undefined error:

TypeError: Cannot read property 'name' of undefined
    at Object.getFunctionName (/home/bogdan/nure/courseProject/DrOwn-server/node_modules/inversify/lib/utils/serialization.js:94:11)
    at Object.getDependencies (/home/bogdan/nure/courseProject/DrOwn-server/node_modules/inversify/lib/planning/reflection_utils.js:11:43)
    at /home/bogdan/nure/courseProject/DrOwn-server/node_modules/inversify/lib/planning/planner.js:106:51
    at Array.forEach (<anonymous>)
    at _createSubRequests (/home/bogdan/nure/courseProject/DrOwn-server/node_modules/inversify/lib/planning/planner.js:94:20)
    at Object.plan (/home/bogdan/nure/courseProject/DrOwn-server/node_modules/inversify/lib/planning/planner.js:136:9)
    at /home/bogdan/nure/courseProject/DrOwn-server/node_modules/inversify/lib/container/container.js:317:37
    at Container._get (/home/bogdan/nure/courseProject/DrOwn-server/node_modules/inversify/lib/container/container.js:310:44)
    at Container.get (/home/bogdan/nure/courseProject/DrOwn-server/node_modules/inversify/lib/container/container.js:230:21)
    at Object.<anonymous> (/home/bogdan/nure/courseProject/DrOwn-server/dist/services/authentication.service.js:21:41)
    at Module._compile (internal/modules/cjs/loader.js:688:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:699:10)
    at Module.load (internal/modules/cjs/loader.js:598:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:537:12)
    at Function.Module._load (internal/modules/cjs/loader.js:529:3)
    at Module.require (internal/modules/cjs/loader.js:636:17)

Possible Solution



None. I have tried all the pieces of advice from #584, #488 and #961 (the closest one, I think it is similar to mine).

Steps to Reproduce (for bugs)



The problem is I have tried to create minimalistic example that shows this error, but every time I tried to do this (outside and inside) the project I failed. In fact, it works even within current project (from the CLI database script). So my example is this project (sorry to bother you with >3000 dependencies :) ).
Steps to start the project:

  1. git clone https://github.com/shevchenkobn/DrOwn-server.git
  2. git checkout f676ae87b13a8372e00401e2cd1e5bc04810032b
  3. npm i
  4. npm start (the JS code is built and up-to-date; if you want to rebuild it run npm run build. In this case you would probably install devDependencies by npm i -D and npm run npm:g:dev or npm run npm:g:dev:win - global packages for development)
  5. See the error.

Context



Possibly, the issue is connected with sideeffects of either Inversify with reflect-metadata or some other packages and may be relevant to other developers. Again, the issue is similar to #961

I really liked your package but, unfortunately, I have to use some alternative DI library. Hope the issues is resolved and I will get back to Inversify.

Your Environment

Stack trace

TypeError: Cannot read property 'name' of undefined
    at Object.getFunctionName (/home/bogdan/nure/courseProject/DrOwn-server/node_modules/inversify/lib/utils/serialization.js:94:11)
    at Object.getDependencies (/home/bogdan/nure/courseProject/DrOwn-server/node_modules/inversify/lib/planning/reflection_utils.js:11:43)
    at /home/bogdan/nure/courseProject/DrOwn-server/node_modules/inversify/lib/planning/planner.js:106:51
    at Array.forEach (<anonymous>)
    at _createSubRequests (/home/bogdan/nure/courseProject/DrOwn-server/node_modules/inversify/lib/planning/planner.js:94:20)
    at Object.plan (/home/bogdan/nure/courseProject/DrOwn-server/node_modules/inversify/lib/planning/planner.js:136:9)
    at /home/bogdan/nure/courseProject/DrOwn-server/node_modules/inversify/lib/container/container.js:317:37
    at Container._get (/home/bogdan/nure/courseProject/DrOwn-server/node_modules/inversify/lib/container/container.js:310:44)
    at Container.get (/home/bogdan/nure/courseProject/DrOwn-server/node_modules/inversify/lib/container/container.js:230:21)
    at Object.<anonymous> (/home/bogdan/nure/courseProject/DrOwn-server/dist/services/authentication.service.js:21:41)
    at Module._compile (internal/modules/cjs/loader.js:688:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:699:10)
    at Module.load (internal/modules/cjs/loader.js:598:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:537:12)
    at Function.Module._load (internal/modules/cjs/loader.js:529:3)
    at Module.require (internal/modules/cjs/loader.js:636:17)

Most helpful comment

I have fixed this issue.
If you have a complex project with lots of dependencies and you don't have to worry about the way they are resolved just add import './pass/to/your/di.container'; at the beginning of the file. di.container in this context is file where you create container and add all dependencies there. Example: https://github.com/shevchenkobn/NewCMMS-server/blob/master/src/di/container.ts

_Explanation:_
tl;dr: check your import tree manually. Consider moving objects managed by your DI into separate files in a type-per-file manner. It may be issue with circular imports or similar.

Node modules that have your @injectables probably import their @inject types directly (not for instantiation). Imports are done at the beginning of the file when @injectable type is not even declared. So if your module with @injectable is imported in DI container module, it _may_ get an undefined instead of your @injectable. That is what I had. Inversify tries to report the problem and fails.

Maybe a safeguard should be added to the library? It would be better to check if the type is undefined and report it before trying to read its name.
Something like Error: The dependency Symbol.for(type) is not defined. Consider reordering imports or import your container in the entry-point file.

All 3 comments

I have fixed this issue.
If you have a complex project with lots of dependencies and you don't have to worry about the way they are resolved just add import './pass/to/your/di.container'; at the beginning of the file. di.container in this context is file where you create container and add all dependencies there. Example: https://github.com/shevchenkobn/NewCMMS-server/blob/master/src/di/container.ts

_Explanation:_
tl;dr: check your import tree manually. Consider moving objects managed by your DI into separate files in a type-per-file manner. It may be issue with circular imports or similar.

Node modules that have your @injectables probably import their @inject types directly (not for instantiation). Imports are done at the beginning of the file when @injectable type is not even declared. So if your module with @injectable is imported in DI container module, it _may_ get an undefined instead of your @injectable. That is what I had. Inversify tries to report the problem and fails.

Maybe a safeguard should be added to the library? It would be better to check if the type is undefined and report it before trying to read its name.
Something like Error: The dependency Symbol.for(type) is not defined. Consider reordering imports or import your container in the entry-point file.

@shevchenkobn I've run into this issue recently. Could you elaborate on what you mean by:

"If you have a complex project with lots of dependencies and you don't have to worry about the way they are resolved just add import './pass/to/your/di.container'; at the beginning of the file."?

@shevchenkobn I've run into this issue recently. Could you elaborate on what you mean by:

"If you have a complex project with lots of dependencies and you don't have to worry about the way they are resolved just add import './pass/to/your/di.container'; at the beginning of the file."?

I have updated the previous post. Please, reread the passage you quoted and tl;dr section.

Was this page helpful?
0 / 5 - 0 ratings