nestjs icon indicating copy to clipboard operation
nestjs copied to clipboard

Metadata for entity CustomBaseEntity not found

Open thiagomini opened this issue 2 years ago • 3 comments

Describe the bug

  • Given we are using Entity Schema definitions
  • And we have a CustomBaseEntity abstract class with its schema
  • And we have a User entity class with its schema
  • And both schemas were imported in the module using MikroORMModule.forFeature([customBaseEntitySchema, userSchema])
  • And we're using the autoLoadEntitites: true option.
  • When we initialize a Nest module
  • Then we got an error: MetadataError: Metadata for entity CustomBaseEntity not found

Stack trace

stdout | src/mikro-orm/mikro-orm-internal.module.spec.ts > MikroOrmInternalModule > connects to the database
[info] MikroORM version: 5.7.14
[discovery] ORM entity discovery started, using ReflectMetadataProvider
[discovery] - processing entity CustomBaseEntity
[discovery] - processing entity User
[discovery] - entity discovery finished, found 2 entities, took 11 ms

stdout | src/mikro-orm/mikro-orm-internal.module.spec.ts > MikroOrmInternalModule > connects to the database
[info] MikroORM successfully connected to database postgres on postgresql://postgres:*****@localhost:5435

stdout | src/mikro-orm/mikro-orm-internal.module.spec.ts > MikroOrmInternalModule > connects to the database
[query] select 1 from pg_database where datname = 'postgres' [took 1 ms, 1 result]

 ✓ src/app.controller.spec.ts (1)
 ❯ src/mikro-orm/mikro-orm-internal.module.spec.ts (2) 53117ms
   ❯ MikroOrmInternalModule (2) 53116ms
     × connects to the database 53114ms
       ⠴ [ beforeEach ]
       ⠸ [ afterEach ]
     ↓ creates a new user [skipped]

⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯ Failed Tests 1 ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯

 FAIL  src/mikro-orm/mikro-orm-internal.module.spec.ts > MikroOrmInternalModule > connects to the database
MetadataError: Metadata for entity CustomBaseEntity not found
 ❯ Function.missingMetadata node_modules/@mikro-orm/core/errors.js:178:16
 ❯ MetadataStorage.get node_modules/@mikro-orm/core/metadata/MetadataStorage.js:54:42
 ❯ SqlEntityManager.getRepository node_modules/@mikro-orm/core/EntityManager.js:65:40
 ❯ SqlEntityManager.getRepository node_modules/@mikro-orm/knex/SqlEntityManager.js:41:22
 ❯ InstanceWrapper.useFactory [as metatype] node_modules/@mikro-orm/nestjs/mikro-orm.providers.js:98:34
 ❯ TestingInjector.instantiateClass node_modules/@nestjs/core/injector/injector.js:368:55
 ❯ callback node_modules/@nestjs/core/injector/injector.js:65:45
 ❯ TestingInjector.resolveConstructorParams node_modules/@nestjs/core/injector/injector.js:144:24
 ❯ TestingInjector.loadInstance node_modules/@nestjs/core/injector/injector.js:70:13

To Reproduce Steps to reproduce the behavior:

  1. Clone the minimum reproducible code repository: https://github.com/thiagomini/nest-mikro-orm-example/tree/bug/custom-base-entity
  2. run yarn
  3. run docker compose up -d
  4. run yarn test

Expected behavior The module should have been initialized correctly.

Additional context I'm using Vitest for tests, for it also fails using Jest.

Versions

Dependency Version
node 18.12.1
typescript 5.1.3
mikro-orm 5.7.14
pg 8.11.2

thiagomini avatar Aug 10 '23 14:08 thiagomini

And both schemas were imported in the module using MikroORMModule.forFeature([customBaseEntitySchema, userSchema])

This is your problem, base entities don't exist on runtime, you cannot call forFeature on those. The forFeature call only registers the repositories to the nest DI container, and a base entity does not represent anything. They are inlined to the actual entities that extend them during discovery phase.

FYI in current version you don't have to discover base entities, they will be discovered automatically. In fact, any entity that is referred by a class reference is discovered automatically, e.g. if your Book entity has a m:1 relation to Author entity specified as @ManyToOne(() => Author), that Author entity is also discovered automatically.

So things should work just fine if you do MikroORMModule.forFeature([userSchema]) instead.


I guess we could ignore base entities in the forFeature call, as they won't break anything, it's just a no-op to have them there. But that would be probably a bit bigger refactor, as we would have to be able to tell whether something is a known base entity, which we currently can't do, once the ORM is initialized, those are simply not there at all.

B4nan avatar Aug 10 '23 14:08 B4nan

Hey @B4nan , I appreciate the feedback, but even when I remove the baseEntitySchema from the registration process (see test here) it still gives me the same error:

MetadataError: Metadata for entity CustomBaseEntity not found

Could you help me further with that? Thanks!

Edit: I believe this has to do with two facts:

  1. I'm using schemas to register the entities
  2. I'm using the autoLoadEntities: true configuration

I think the problem is that using the autoLoadEntities requires us to register schemas using the forFeature() method. Still, as you said, apparently we shouldn't be registering the base entity schema like that. Is there any other solution?

thiagomini avatar Aug 10 '23 14:08 thiagomini

Sure, I will take a closer look at the repro when I have a moment, let's reopen then.

B4nan avatar Aug 10 '23 14:08 B4nan

https://github.com/mikro-orm/nestjs/pull/151#issuecomment-2119305771

B4nan avatar May 19 '24 17:05 B4nan