Sequelize: Class constructor Model cannot be invoked without 'new' and how getter v4 work?

Created on 25 Jun 2017  路  30Comments  路  Source: sequelize/sequelize

Hi all,
I using v4 to defined my model as:

@Options({
    sequelize,
    tableName: 'V2_category',
    timestamps: false
})
@Attributes({
    id: {
        type: DataTypes.INTEGER,
        allowNull: false,
        primaryKey: true,
        autoIncrement: true
    },
    name: DataTypes.STRING,
    name_vi: DataTypes.STRING,
    code: DataTypes.STRING,
    type: DataTypes.STRING,
    created_at: DataTypes.DATE,
    updated_at: DataTypes.DATE,
})
export class V2Category extends Model {
    get fullName() {
        return this.name + '-' + this.name_vi;
    }

    set fullName(fullName) {
        const names = fullName.split(' ');
        this.name = names.pop();
        this.name_vi = names.join(' ');
    }
}

and i import in others:
import {V2Category as category} from '../models/V2_category';

my query :
findCategoryById (id) { return category.findOne({ where: { 'id': id } }); }

When run i got an error:

Unhandled rejection TypeError: Class constructor Model cannot be invoked without 'new'

However, i add { where: { 'id': id }, raw: true } my code working but i can't use getter function fullName. Could you tell me where my mistake and how to fix it? Thanks

babel

Most helpful comment

Intypescript case, my solution was to change target from es5 to es6

{
  "compilerOptions": {
    "target": "es6", // <=
    // ...
  }
}

All 30 comments

Please post the whole stack trace

I had the same problem

During debugging I found out that the Model constructor returns a class instead of a function

I have a suspicion that the problem arises at the moment of inheritance

In JavaScript, a class is a function.

@felixfbecker nice joke, I'm very familiar with JS
I could not understand why he inherited this error when he inherited
But if you go the old way and use define, the error disappears
static build(values, options) {
if (Array.isArray(values)){
return this.bulkBuild(values, options);
}
return new this(values, options); }`

I have the same problem.

I think it has something to do with the way babel transpiles the code. After I changed my .babelrc file to this:

{
  "presets": [
    ["env", {
      "targets": {
        "node": "current"
      }
    }]
  ]
}

it works as expected.

Yes, that is very likely.
@zonorion could you post the transpiled JS of that model?

Intypescript case, my solution was to change target from es5 to es6

{
  "compilerOptions": {
    "target": "es6", // <=
    // ...
  }
}

I'm getting this as well. Just upgraded from 3 to 4.4.2, and when I change my model definitions to:

const attributes = {/*...*/};
const options = {
  sequelize,
};
class User extends Sequelize.Model {
  someInstanceMethod() {}
}
User.someStaticMethod = () => {};
User.init(attributes, options);

I started seeing the error anytime Sequelize attempted to create an instance of User (such as User.findOne()).

My .babelrc:

{
  "presets": ["es2015", "react", "stage-0"]
}

Switching to this for now:

const User = sequelize.define('User', attributes, options);
User.prototype.someInstanceMethod = function() {}; // function can't be () => {}
User.someClassMethod = () => {};

@juhaelee says:

You just need to use the env preset package instead of es2015
```{
"presets": [
["env", {
"targets": {
"node": "current"
}
}],
"stage-1"
],
"plugins": []
}

Sr, i missed any notifications
I used:
{ "presets": [ "es2015-node6", "stage-3" ], "plugins": [ ["transform-decorators-legacy"], [ "transform-runtime", { "polyfill": false, "regenerator": true } ], [ "istanbul", { "exclude": [ "test/*.js" ] } ] ] }

sequelize woking fine!

It turns out that an ES6-class transpiled by babel can't extend a real ES6 class (The Sequelize.Model ES6-class for example).

So class MyEntity extends Sequelize.Model { ... } won't work if MyEntity is transpiled into ES5.

See https://stackoverflow.com/questions/36577683/babel-error-class-constructor-foo-cannot-be-invoked-without-new

The solution i used, was to use es2015-node5 instead of es2015. But ONLY on the server, of course, not on the client - i.e. not when transpiling for the browser. So i didn't put this in my .babelrc, but added it to the "build-server" command-line scripts in package.json instead: babel .... --no-babelrc --presets=es2015-node5,stage-0,react.

have almost the same problem how do i solve it ... looking for a solution

@corneliouzbett

have almost the same problem how do i solve it ... looking for a solution

do you found solution ?

I'm getting this error as well when using some of the example code listed within Express / Sequelize setup. Seems the the offending line of code is within the cli's default generated models/index.js

const model = sequelize['import'](path.join(__dirname, file))

Altered things with babel and so forth, but haven't gotten it working just yet.

Turns out in my case, I had a previously created model in the models folder that was causing things to break:

const Sequelize = require('sequelize')
const db = require('../sequelize')

const Post = db.define('post', {
    title: Sequelize.STRING(255),
    body: Sequelize.TEXT('long'),
    excerpt: Sequelize.STRING(500),
    tags: Sequelize.STRING(500),
    slug: Sequelize.STRING(255),
    thumbnail_path: Sequelize.STRING(255),
    hero_path: Sequelize.STRING(255),
    updatedAt: Sequelize.DATE
})

module.exports = Post

This was preventing the file from being read correctly by sequelize and causing the error listed in this thread. Advice for others: Make sure all of your code inside of your models folder is valid and from examples.

For those running into this, this is a bug in babel. I haven't been able to solve it on my end using the suggested solutions likely because I use babel runtime transformations. There is a PR open @babel to resolve this. Hopefully it will be merged soon. https://github.com/babel/babel/pull/8656

Mine got solved via:

{
  "presets": [
    [
      "@babel/preset-env",
      {
        "targets": {
          "node": true
        }
      }
    ]
  ]
}

Im not using a transpiler and i have this error as well

Same issue here and my .babelrc is:

{
  "presets": [
    [
      "@babel/preset-env",
      {
        "targets": {
          "node": "current"
        }
      }
    ]
  ]
}

Any other suggestions to solve this?

Just in case it helps someone else: in my case the issue was that I was using --presets @babel/preset-env with the babel command, so my babel.config.js file with presets: [['@babel/preset-env', {targets: {node: 'current'}}]] was being ignored...

For anyone having trouble with this using Jest and Expo (React Native), you may need to add sequelize to to the transformIgnorePatterns in the jest config.


My jest.config.js

module.exports = {
  preset: "jest-expo",
  reporters: [
    "default",
    [
      "./node_modules/jest-html-reporters",
      {
        filename: "./public/test-report.html",
        pageTitle: "BioPointe: Unit Tests",
      },
    ],
  ],
  coverageDirectory: "./public/coverage",
  snapshotSerializers: ["./src/BioPointe.serializer.js"],
  transformIgnorePatterns: [
    "node_modules/(?!((jest-)?" +
      // If having issues with complation/runtime in tests regarding language
      // features, you may want to add entries to this array for the relevant
      // modules.
      [
        "react-native",
        "react-clone-referenced-element",
        "expo(nent)?",
        "@unimodules/.*",
        "jest-expo/.*",
        "@expo(nent)?/.*",
        "react-navigation",
        "@react-navigation/.*",
        "sentry-expo",
        "sequelize",
        "native-base",
        "@sentry/.*",
        "unimodules-.*",
      ].join("|") +
      "))",
  ],
};

For anyone who comes to this and the reason was not transpiling. For me it was because I was exporting my models as classes, and the line from the generated models/index.js :

const model = sequelize['import'](path.join(__dirname, file))

was causing the error. Once I changed that line to:

let model = require(path.join(__dirname, file));

It was fixed

Hi guys, I have the same issue with tsc (TypeScript compiler).

tscconfig.json

{
  "compilerOptions": {
    "target": "ES6",
    "module": "CommonJS",
    "moduleResolution": "node",
    "lib": ["ES5", "ES6"],
    "declaration": true,
    "outDir": "./build",
    "strict": true,
    "esModuleInterop": true,
    "allowJs": false,
    "allowSyntheticDefaultImports": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "strictPropertyInitialization": false,
    "sourceMap": true
  },
  "include": ["src"],
  "exclude": ["node_modules"]
}

version

{
  "sequelize": "^5.21.6",
  "ts-node": "^8.10.1",
  "typescript": "^3.7.2"
}

model

import { Model, DataTypes } from 'sequelize';
import sequelize from './';
import { OrderStatus } from '../components/constants';

class Order extends Model {
  public id!: number;
  public total!: number;
  public finalTotal!: number;
  public status: OrderStatus;
  public start_date: Date;
  public end_date: Date;
  public created_at: Date;
  public updated_at: Date;
}

Order.init({
  id: {
    type: DataTypes.UUID,
    primaryKey: true,
    defaultValue: DataTypes.UUIDV4
  },
  total: {
    type: DataTypes.INTEGER,
    allowNull: true,
  },
  finalTotal: {
    type: DataTypes.INTEGER,
    allowNull: true,
    validate: {
      len: {
        args: [2, 5],
        msg: 'Name must be from 2 to 5 characters in length'
      },
    }
  },
  status: {
    type: DataTypes.ENUM(OrderStatus.InProcess, OrderStatus.Done)
  },
}, {
  sequelize,
  tableName: 'orders',
})

export default Order;

sequelize.import

const modelsPath = `${__dirname}/../src/models`;
  const models = fs
    .readdirSync(modelsPath)
    .filter((filename: string) => /model.ts$/.test(filename))
    .reduce((total: any, filename: string) => {
      const model = sequelize.import(path.join(modelsPath, filename));
      total[capitalize(model.name)] = model;
      return total;
    }, {});

  // Sets up the associations for each model.
  Object.keys(models).forEach((modelName: string) => {
    if ('associate' in models[modelName]) {
      models[modelName].associate(models);
    }
  });

error

TypeError: Class constructor Order cannot be invoked without 'new'
      at Sequelize.import (node_modules/sequelize/lib/sequelize.js:486:38)
      at /home/cuongw/Workspace/SaveMoney/service-template/test/utils.ts:18:37
      at Array.reduce (<anonymous>)
      at Object.exports.prepareModels (test/utils.ts:17:6)
      at Object.exports.loadFixtures (test/utils.ts:35:18)
      at Context.<anonymous> (test/order.test.ts:16:11)
      at processImmediate (internal/timers.js:456:21)

Please tell me a solution. Thank all.

I had the same error with typescript and it was fixed when I updated the tsconfig.json changing the es5 for es6

"compilerOptions": {
"target": "es6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. /
"module": "commonjs", /
Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */

I had the same error with typescript and it was fixed when I updated the tsconfig.json changing the es5 for es6

"compilerOptions": {
"target": "es6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. _/ "module": "commonjs", /_ Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */

Thank for your reply. I used ES6 for target but it doesn't work.

Hi guys, I have the same issue with tsc (TypeScript compiler).

tscconfig.json

{
  "compilerOptions": {
    "target": "ES6",
    "module": "CommonJS",
    "moduleResolution": "node",
    "lib": ["ES5", "ES6"],
    "declaration": true,
    "outDir": "./build",
    "strict": true,
    "esModuleInterop": true,
    "allowJs": false,
    "allowSyntheticDefaultImports": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "strictPropertyInitialization": false,
    "sourceMap": true
  },
  "include": ["src"],
  "exclude": ["node_modules"]
}

version

{
  "sequelize": "^5.21.6",
  "ts-node": "^8.10.1",
  "typescript": "^3.7.2"
}

model

import { Model, DataTypes } from 'sequelize';
import sequelize from './';
import { OrderStatus } from '../components/constants';

class Order extends Model {
  public id!: number;
  public total!: number;
  public finalTotal!: number;
  public status: OrderStatus;
  public start_date: Date;
  public end_date: Date;
  public created_at: Date;
  public updated_at: Date;
}

Order.init({
  id: {
    type: DataTypes.UUID,
    primaryKey: true,
    defaultValue: DataTypes.UUIDV4
  },
  total: {
    type: DataTypes.INTEGER,
    allowNull: true,
  },
  finalTotal: {
    type: DataTypes.INTEGER,
    allowNull: true,
    validate: {
      len: {
        args: [2, 5],
        msg: 'Name must be from 2 to 5 characters in length'
      },
    }
  },
  status: {
    type: DataTypes.ENUM(OrderStatus.InProcess, OrderStatus.Done)
  },
}, {
  sequelize,
  tableName: 'orders',
})

export default Order;

sequelize.import

const modelsPath = `${__dirname}/../src/models`;
  const models = fs
    .readdirSync(modelsPath)
    .filter((filename: string) => /model.ts$/.test(filename))
    .reduce((total: any, filename: string) => {
      const model = sequelize.import(path.join(modelsPath, filename));
      total[capitalize(model.name)] = model;
      return total;
    }, {});

  // Sets up the associations for each model.
  Object.keys(models).forEach((modelName: string) => {
    if ('associate' in models[modelName]) {
      models[modelName].associate(models);
    }
  });

error

TypeError: Class constructor Order cannot be invoked without 'new'
      at Sequelize.import (node_modules/sequelize/lib/sequelize.js:486:38)
      at /home/cuongw/Workspace/SaveMoney/service-template/test/utils.ts:18:37
      at Array.reduce (<anonymous>)
      at Object.exports.prepareModels (test/utils.ts:17:6)
      at Object.exports.loadFixtures (test/utils.ts:35:18)
      at Context.<anonymous> (test/order.test.ts:16:11)
      at processImmediate (internal/timers.js:456:21)

Please tell me a solution. Thank all.

I resolved my issue. I used require instead of sequelize.import. 馃槗

Intypescript case, my solution was to change target from es5 to es6

{
  "compilerOptions": {
    "target": "es6", // <=
    // ...
  }
}

Works for me! Thanks

let model = require(path.join(__dirname, file))

I am having the same issue, changed the appropriate line, still no luck.

After much searching I found that this error does sometimes occur when the entity column type cannot be inferred.

These are the only values that can automap:
string | STRING
boolean | BOOLEAN
number | INTEGER
bigint | BIGINT
Date | DATE
Buffer | BLOB

If you are using any other value, for example a UUID you need to set that in the column annotation
@Column({type: DataType.UUIDV4})

Hope that helps anyone else going down this rabbit hole.

Was this page helpful?
0 / 5 - 0 ratings