{"id":"f73a514a896ac83e","repo":"typeorm/typeorm","slug":"cannot-operation-given-value-must-be-instance","errorCode":null,"errorMessage":"Cannot ${operation}, given value must be instance of entity class, instead object literal is given. Or you must specify an entity target to method call.","messagePattern":"Cannot (.+?), given value must be instance of entity class, instead object literal is given\\. Or you must specify an entity target to method call\\.","errorType":"exception","errorClass":"CannotDetermineEntityError","httpStatus":null,"severity":"error","filePath":"src/persistence/EntityPersistExecutor.ts","lineNumber":79,"sourceCode":"        try {\n            // collect all operate subjects\n            const entities: ObjectLiteral[] = Array.isArray(this.entity)\n                ? this.entity\n                : [this.entity]\n            const chunkSize = this.options?.chunk ?? 0\n            const entitiesInChunks =\n                chunkSize > 0 ? OrmUtils.chunk(entities, chunkSize) : [entities]\n\n            const buildExecutor = async (\n                entities: ObjectLiteral[],\n            ): Promise<SubjectExecutor> => {\n                const subjects: Subject[] = []\n\n                // create subjects for all entities we received for the persistence\n                entities.forEach((entity) => {\n                    const entityTarget = this.target ?? entity.constructor\n                    if (entityTarget === Object)\n                        throw new CannotDetermineEntityError(this.mode)\n\n                    const metadata = this.dataSource\n                        .getMetadata(entityTarget)\n                        .findInheritanceMetadata(entity)\n\n                    subjects.push(\n                        new Subject({\n                            metadata,\n                            entity: entity,\n                            canBeInserted: this.mode === \"save\",\n                            canBeUpdated: this.mode === \"save\",\n                            mustBeRemoved: this.mode === \"remove\",\n                            canBeSoftRemoved: this.mode === \"soft-remove\",\n                            canBeRecovered: this.mode === \"recover\",\n                        }),\n                    )\n                })\n","sourceCodeStart":61,"sourceCodeEnd":97,"githubUrl":"https://github.com/typeorm/typeorm/blob/04ff4daedcf60fa4ffd0d5d33bbafaac1a9bbc96/src/persistence/EntityPersistExecutor.ts#L61-L97","documentation":"Thrown as `CannotDetermineEntityError` inside `EntityPersistExecutor.execute()` when the entity target cannot be inferred: the passed value is a plain object literal whose `constructor === Object`, and no explicit `target` (entity class) was supplied to the persist call. TypeORM needs an entity class to look up metadata; without it, save/remove/etc. is refused.","triggerScenarios":"`dataSource.manager.save({ name: \"x\" })` with a plain object and no class; `repository.save([{ id: 1 }])` where elements are object literals; calling `entityManager.persist(target=undefined, plainObject)`; spreading a class instance into a plain object (`{ ...user }`) before saving.","commonSituations":"Refactoring from class instances to plain DTOs; passing parsed JSON bodies directly to save; using `Object.assign({}, entity)` which strips the prototype; mixing repository-style (`repo.save(plainObj)`) with entityManager-style without a target.","solutions":["Construct an entity instance before saving: `manager.save(Object.assign(new User(), dto))`.","Pass the entity target explicitly as the first argument: `manager.save(User, dto)` or `manager.save(User, [dto1, dto2])`.","When using a repository, ensure the values retain their class prototype (avoid `JSON.parse` / spread that produces plain objects)."],"exampleFix":"// before\nawait dataSource.manager.save({ name: \"Alex\", email: \"a@b.c\" })\n\n// after — pass the target explicitly\nawait dataSource.manager.save(User, { name: \"Alex\", email: \"a@b.c\" })\n// or construct an instance\nconst u = Object.assign(new User(), { name: \"Alex\", email: \"a@b.c\" })\nawait dataSource.manager.save(u)","handlingStrategy":"type-guard","validationCode":"// Reject plain object literals before persistence\nfunction assertEntityInstance(value: any, target?: Function): void {\n  if (!target && value?.constructor === Object) {\n    throw new Error(\"Refusing to persist a plain object literal; pass a target or an instance\")\n  }\n}","typeGuard":"function isEntityInstance<T>(value: any, target: new () => T): value is T {\n  return value instanceof target\n}","tryCatchPattern":"try {\n  await manager.save(value)\n} catch (e) {\n  if (e instanceof CannotDetermineEntityError) {\n    await manager.save(Target, value) // retry with explicit target\n  } else throw e\n}","preventionTips":["Always construct entity instances (`new User()`) rather than passing plain objects from req.body.","When using DTOs, map them onto instances via `Object.assign(new User(), dto)` or a mapper.","Prefer the repository API (`userRepo.save(...))`, which binds the target automatically."],"tags":["persistence","save","entity","type-guard"],"analyzedSha":"04ff4daedcf60fa4ffd0d5d33bbafaac1a9bbc96","analyzedAt":"2026-08-03T18:27:32.281Z","schemaVersion":2}