typeorm: Cannot perform update query because update values are not defined.

Issue type:

[x] question [ ] bug report [ ] feature request [ ] documentation issue

Database system/driver:

[ ] cordova [ ] mongodb [ ] mssql [ ] mysql / mariadb [ ] oracle [x] postgres [ ] cockroachdb [ ] sqlite [ ] sqljs [ ] react-native [ ] expo

TypeORM version:

[x] latest [ ] @next [ ] 0.x.x (or put your version here)

I am getting an error when trying to save to the database. It looks like I’m just misunderstanding saving with a repository or perhaps how the promise works in this situation, but any help would be great.

I am including a break down of all the files, sorry its long!

Here is the error I’m seeing surfaced from my docker instance.

Error caught:  { UpdateValuesMissingError: Cannot perform update query because update values are not defined. Call "qb.set(...)" method to specify updated values.
experiments_ms_1  |     at new UpdateValuesMissingError (/experiments-service/src/error/UpdateValuesMissingError.ts:8:9)
experiments_ms_1  |     at UpdateQueryBuilder.createUpdateExpression (/experiments-service/src/query-builder/UpdateQueryBuilder.ts:456:19)
experiments_ms_1  |     at UpdateQueryBuilder.getQuery (/experiments-service/src/query-builder/UpdateQueryBuilder.ts:45:24)
experiments_ms_1  |     at UpdateQueryBuilder.QueryBuilder.getQueryAndParameters (/experiments-service/src/query-builder/QueryBuilder.ts:385:28)
experiments_ms_1  |     at UpdateQueryBuilder.<anonymous> (/experiments-service/src/query-builder/UpdateQueryBuilder.ts:82:44)
experiments_ms_1  |     at step (/experiments-service/node_modules/tslib/tslib.js:133:27)
experiments_ms_1  |     at Object.next (/experiments-service/node_modules/tslib/tslib.js:114:57)
experiments_ms_1  |     at /experiments-service/node_modules/tslib/tslib.js:107:75
experiments_ms_1  |     at new Promise (<anonymous>)
experiments_ms_1  |     at Object.__awaiter (/experiments-service/node_modules/tslib/tslib.js:103:16)
experiments_ms_1  |   name: 'UpdateValuesMissingError',
experiments_ms_1  |   message:
experiments_ms_1  |    'Cannot perform update query because update values are not defined. Call "qb.set(...)" method to specify updated values.' }

Steps to reproduce:

Requirements: NodeJs/Express, TypeScript

The following file is out basic file setup.

/entity/Experiment.ts

import {Entity, PrimaryGeneratedColumn, Column, ManyToOne, OneToMany, ManyToMany, JoinTable} from "typeorm";
import { Author } from "./Author";
import { Image } from "./Image";
import { Platform } from './Platform';
import { Variation } from "./Variation";

@Entity()
export class Experiment {

    @PrimaryGeneratedColumn()
    id: number;

    @Column({
        nullable: true
      })
    testplan: string; 
    
    @Column({
        nullable: true
      })
    name: string;

    @Column({
        nullable: true
      })
    isLive: boolean;

    @ManyToOne(type => Author, author => author.experiments)
    author: Author;

    @ManyToOne(type => Platform, platform => platform.experiments)
    platform: Platform;

    @OneToMany(type => Image, image => image.experiment)
    images: Image[];

    @OneToMany(type => Variation, variation => variation.experiment)
    variations: Variation[];
}

/entity/Variation.ts

import {Entity, PrimaryGeneratedColumn, Column, ManyToOne} from "typeorm";
import { Experiment } from "./Experiment";

@Entity()
export class Variation {
    @PrimaryGeneratedColumn()
    id: number;

    @Column()
    url: string;

    @ManyToOne(type => Experiment, experiment => experiment.variations)
    experiment: Experiment;
}

/entity/Image.ts

import {Entity, PrimaryGeneratedColumn, Column, ManyToOne} from "typeorm";
import { Experiment } from "./Experiment";

@Entity()
export class Image {
    @PrimaryGeneratedColumn()
    id: number;

    @Column()
    path: string;

    @ManyToOne(type => Experiment, experiment => experiment.images)
    experiment: Experiment;
}

/entity/Author.ts

import {Entity, PrimaryGeneratedColumn, Column, OneToMany, JoinColumn} from "typeorm";
import {Experiment} from "./Experiment";

@Entity()
export class Author {
    @PrimaryGeneratedColumn()
    id: number;

    @Column()
    firstName: string;

    @Column()
    lastName: string;

    @Column()
    prefs: 'json';

    @OneToMany(type => Experiment, experiment => experiment.author)
    experiments: Experiment[];
}

/entity/Platform.js

import {Entity, PrimaryGeneratedColumn, Column, OneToMany, JoinColumn} from "typeorm";
import {Experiment} from "./Experiment";

@Entity()
export class Platform {
    @PrimaryGeneratedColumn()
    id: number;

    @Column()
    name: string;

    @OneToMany(type => Experiment, experiment => experiment.platform)
    experiments: Experiment[];
}

/index.ts

import "reflect-metadata";
import * as express from "express";
import * as bodyParser from "body-parser";
import {Request, Response} from "express";
import {Routes} from "./routes";
import {createConnection} from "typeorm";

createConnection().then(async connection => {

const app = express();
app.use(bodyParser.json());

// register express routes from defined application routes
Routes.forEach(route => {
    (app as any)[route.method](route.route, (req: Request, res: Response, next: Function) => {
        const result = (new (route.controller as any))[route.action](req, res, next);
        if (result instanceof Promise) {
            result.then(result => result !== null && result !== undefined ? res.send(result) : undefined);

        } else if (result !== null && result !== undefined) {
            res.json(result);
        }
    });
});

// start express server
app.listen(3000);

console.log("Express server has started on port 3000. Open http://localhost:3000/health to see it running.");

}).catch(error => console.log("TypeORM connection error: ", error));

/routes.ts

import {UserController} from "./controller/UserController";
import {ExperimentController} from "./controller/ExperimentController";
import {HealthController} from "./controller/HealthController";

export const Routes = [{
    method: "post",
    route: "/experiments",
    controller: ExperimentController,
    action: "save"
}

/controller/ExperimentController.ts


import {createConnection, getManager} from "typeorm";
import {getRepository} from "typeorm";
import {NextFunction, Request, Response} from "express";
import {Experiment} from "../entity/Experiment";
import {Author} from "../entity/Author";
import {Image} from "../entity/Image";
import {User} from "../entity/User";
import {Variation} from "../entity/Variation";
import { Platform } from "../entity/Platform";

// ... Other functions ...
       async save(request: Request, response: Response, next: NextFunction) {

        const author = new Author();
        author.firstName = "Aaron";
        author.lastName = "Montana";
    
        const platform = new Platform();
        platform.name = "SaaS 1";
        
        const image = new Image();
        image.path = "/path/to/image.svg";

        const v1 = new Variation();
        v1.url = "http://example.com/path1";

        const v2 = new Variation();
        v2.url = "http://example.com/path2";
    
        const experiment = new Experiment();
        experiment.testplan = "https://link.to/document";
        experiment.name = 'Experiment 100';
        experiment.isLive = true;    
        experiment.author = author;
        experiment.platform = platform;
        experiment.images = [image];
        experiment.variations = [v1,v2];

        try{
           let savedExp =  await getManager().getRepository(Experiment).save(experiment);
            console.log("Post has been saved: ", experiment, savedExp);
            response.send(experiment);
        }catch(e){
            console.log('Error caught: ', e);
            response.send(e);
        }   
    }

Thanks for taking a look 😃

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Comments: 16 (2 by maintainers)

Most upvoted comments

Closing this one - I figured it out. Turns out I was missing the cascade option:

 @OneToMany(type => Variation, variation => variation.experiment, {
        cascade: true,
    })

In my case I forgot to add @ JoinColumn at a @ OneToOne relation.

Another source for the problem is sending primary keys in values, for example:

this.categoryRepository.update(input.id, {
      name: input.name,
      slug: input.slug
      // we cannot send id here
})

I am running into a similar issue, where save fails only, when I use @JoinColumn for renaming my columns.

“Cannot perform update query because update values are not defined. Call “qb.set(…)” method to specify updated values.”

When letting TypeORM name the columns by it self everything seems to work.

I got this error because I was trying to set arrays directly in the constructor call instead of loading them into the object after initialization

@jagabs try saving with the different sequence! With one to one relation you should save the one with the join column last if you do not enable {cascade:true} I think the problem is when we try adding the one with the joinColumn() first, the other one is not saved, therefore does not have an Id to fill the relation column. At least this is how it works for me!

I just had this and it was caused by setting {update: false} on a relation column (in my case it was userId which links a profile entity to the corresponding user entity)

I got this mistake by having a @ oneToMany in a case where it should have been @ manyToMany changing it to the correct decorator fixed it.