'Trying to persist not discovered entity of type object

The problem

I'm new to Nest.js and Mikro-ORM, which I have to learn as a job requirement.

This stack requires TypeScript, which I despise from the bottom of my heart, but it has to be done.

I have set up my app and when I execute npm run start:dev, it starts up without a problem.

However, when I try to add something to the database, it spazzes out and gives me the following error block:

[Nest] 5368   - 07/03/2021, 11:52:15 PM   [ExceptionsHandler] Trying to persist not discovered entity of type object. +183188ms
ValidationError: Trying to persist not discovered entity of type object.
    at Function.notDiscoveredEntity (/home/lazar/tuts/backend/node_modules/@mikro-orm/core/errors.js:51:16)
    at SqlEntityManager.persist (/home/lazar/tuts/backend/node_modules/@mikro-orm/core/EntityManager.js:438:48)
    at SqlEntityManager.persistAndFlush (/home/lazar/tuts/backend/node_modules/@mikro-orm/core/EntityManager.js:449:20)
    at SqlEntityRepository.persistAndFlush (/home/lazar/tuts/backend/node_modules/@mikro-orm/core/entity/EntityRepository.js:21:23)
    at UsersService.create (/home/lazar/tuts/backend/dist/users/users.service.js:47:35)
    at UsersController.create (/home/lazar/tuts/backend/dist/users/users.controller.js:25:40)
    at /home/lazar/tuts/backend/node_modules/@nestjs/core/router/router-execution-context.js:38:29
    at processTicksAndRejections (internal/process/task_queues.js:97:5)
    at async /home/lazar/tuts/backend/node_modules/@nestjs/core/router/router-execution-context.js:46:28
    at async /home/lazar/tuts/backend/node_modules/@nestjs/core/router/router-proxy.js:9:17

This is my first time walking into this stack and I have no idea what the error means. When I Google this error, I get nothing useful. What can I do to make it go away?

The relevant code

  • The Entity (User.ts)
import { Entity, PrimaryKey, Property } from "@mikro-orm/core";

@Entity()
export class User {
  @PrimaryKey()
  id!: string;

  @Property()
  email!: string;

  @Property()
  name!: string;

  @Property()
  password!: string;

  @Property({ type: 'date' })
  createdAt = new Date()

  @Property({ type: 'date', onUpdate: () => new Date() })
  updatedAt = new Date()
};
  • The Controller (users.controller.ts)
import { Body, Controller, Delete, Get, Param, Post, Put } from '@nestjs/common';
import { CreateUserDTO } from './dto/create-user.dto';
import { User } from './interfaces/user.interface';
import { UsersService } from './users.service';
import { User as UserEntity } from "../entities/User"

@Controller('users')
export class UsersController {
  constructor(private usersService: UsersService) {}

  @Post()
  async create(@Body() createUserDto: CreateUserDTO): Promise<User> {
    console.log("CREATEUSERDTO", createUserDto);
    return await this.usersService.create(createUserDto)
  }
}
  • The Service (users.service.ts)
import { EntityRepository } from '@mikro-orm/core';
import { Injectable } from '@nestjs/common';
import { User } from './interfaces/user.interface';
import { User as UserEntity } from "../entities/User"
import { InjectRepository } from '@mikro-orm/nestjs';

@Injectable()
export class UsersService {
  constructor(
    @InjectRepository(UserEntity)
    private readonly userRepository: EntityRepository<UserEntity>
  ) {}

  async create(user: User): Promise<UserEntity> {
    console.log("ALL GOOD");
    const newUser = this.userRepository.create(user)
    console.log("ALL GOOD");
    console.log("NEW USER", newUser);
    await this.userRepository.persistAndFlush(user)
    console.log("ALL GOOD");
    return newUser
  }
}
  • The Module (users.module.ts)
import { MikroOrmModule } from '@mikro-orm/nestjs';
import { Module } from '@nestjs/common';
import { User } from 'src/entities/User';
import { UsersController } from './users.controller';
import { UsersService } from './users.service';

@Module({
  imports: [MikroOrmModule.forFeature([User])],
  controllers: [UsersController],
  providers: [UsersService],
  exports: [UsersService]
})
export class UsersModule {}
  • The DTO
export class CreateUserDTO {
  readonly name: string;
  readonly email: string;
  readonly password: string;
  readonly createdAt: Date;
  readonly updatedAt: Date;
}
  • The Interface
export interface User {
  id?: string;
  name: string;
  email: string;
  password: string;
  createdAt: Date;
  updatedAt: Date;
}


Solution 1:[1]

As Micael Levi already pointed out in the comments, this is caused by you trying to persist a POJO/DTO instead of entity instance.

const dto = { name: '...', email: '...' };
const user = em.create(User, dto);

// this is basically what you are doing and will fail as the prototype
// is just `Object` - which is what you see in the error
em.persist(dto);

// and this is what you need to do instead
em.persist(user);

You always need to work with entity instances so the ORM will know what metadata to use. If you have just Object there is no way to associate the object with correct database table.

Solution 2:[2]

I had the same issue and i believe the error is related to identity map context, by using merge it should add it to the context map that the entity manager uses.

em.merge(row)

"Merges given entity to this EntityManager so it becomes managed. You can force refreshing of existing entities via second parameter. By default it will return already loaded entities without modifying them."

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Martin Adámek
Solution 2 jen