'TypeORM CLI: No changes in database schema were found

I'm am developing an application using NestJS and TypeORM. Whenever I try to generate migrations from my entities (by running typeorm migration:generate) I get the following message:

No changes in database schema were found - cannot generate a migration. To create a new empty migration use "typeorm migration:create" command

I even deleted all the existing migration files (from migrations folder) to exclude any possibility of conflict.

The problem begun after I changed my application's modules folders structure to:

src
 |- config
 |   |- database
 |       |- mysql
 |           |- cli-configuration.ts
 |- migrations
 |- module1
     |- controller
     |- entity
     |- service

As can be seen, the migrations folder is right under src and each module has an entity folder, where the entities for that module are placed. All the ormconfig settings come from cli-configuration.ts file.

In package.json file I added the following to scripts:

{
  ...
  "scripts": {
    ...
    "typeorm": "ts-node -r tsconfig-paths/register ./node_modules/typeorm/cli.js --config src/config/database/mysql/cli-configuration.ts",
    "typeorm:migrate": "npm run typeorm migration:generate -- -n",
    "typeorm:run": "npm run typeorm migration:run"
  }
}

The content of src/config/database/mysql/cli-configuration.ts file is:

import * as path from 'path';
import * as dotenv from 'dotenv';

dotenv.config({
  // Path relative to project root folder (because cli command is invoked from there)
  path: path.resolve('environment', (process.env.NODE_ENV === "production") ? ".env.production" : ".env")
});

const config = {
  type: "mysql",
  host: process.env.TYPEORM_HOST,
  port: Number(process.env.TYPEORM_PORT),
  username: process.env.TYPEORM_USERNAME,
  password: process.env.TYPEORM_PASSWORD,
  database: process.env.TYPEORM_DATABASE,
  entities: [path.resolve('src', process.env.TYPEORM_ENTITIES)],

  // We are using migrations, synchronize should be set to false.
  synchronize: false,

  // Run migrations automatically,
  // you can disable this if you prefer running migration manually.
  migrationsRun: true,
  logging: process.env.TYPEORM_LOGGING,

  // Allow both start:prod and start:dev to use migrations
  // __dirname is either dist or src folder, meaning either
  // the compiled js in prod or the ts in dev.
  migrations: [path.resolve('src', process.env.TYPEORM_MIGRATIONS)],
  cli: {
    // Location of migration should be inside src folder
    // to be compiled into dist/ folder.
    // entitiesDir: process.env.TYPEORM_ENTITIES_DIR,
    migrationsDir: path.resolve('src', process.env.TYPEORM_MIGRATIONS_DIR),
    // subscribersDir: process.env.TYPEORM_SUBSCRIBERS_DIR,
  },
  dropSchema: false
};

export = config;

Running console.log(config) I get:

{
  type: 'mysql',
  host: 'localhost',
  port: 3306,
  username: 'root',
  password: 'root',
  database: 'myapp',
  entities: [ '/var/www/html/myapp/src/**/*.entity{.ts,.js}' ],
  synchronize: false,
  migrationsRun: true,
  logging: 'all',
  migrations: [ '/var/www/html/myapp/src/migrations/**/*{.ts,.js}' ],
  cli: { migrationsDir: '/var/www/html/myapp/src/migrations' },
  dropSchema: false
}

Last but not least.... After spending hours on this issue (making changes to migrations and entities paths, hard-coding values besides getting them from process.env, etc), I tried to execute yarn run typeorm schema:log (npm run works as well). I got surprised when I saw that all the content that I expected to be in the migration file I am trying to generate was output to console.

CREATE TABLE `permission_permission` (`id` varchar(36) NOT NULL, `name` varchar(100) NOT NULL, `code` text NOT NULL, `create_date` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), `update_date` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), `delete_date` datetime(6) NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB;
CREATE TABLE `permission_role` (`id` varchar(36) NOT NULL, `name` varchar(100) NOT NULL, `code` varchar(255) NOT NULL, `create_date` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), `update_date` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), `delete_date` datetime(6) NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB;
CREATE TABLE `user_user` (`id` varchar(36) NOT NULL, `email` varchar(255) NOT NULL, `password` varchar(255) NOT NULL, `first_name` varchar(255) NOT NULL, `last_name` varchar(255) NOT NULL, `is_active` tinyint NOT NULL DEFAULT 0, `create_date` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), `update_date` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), `delete_date` datetime(6) NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB;
CREATE TABLE `permission_role_permission` (`permission_id` varchar(36) NOT NULL, `role_id` varchar(36) NOT NULL, INDEX `IDX_3247040996395a5faea3c9b3a5` (`permission_id`), INDEX `IDX_7d9cfbfd027256ab08658bcf6e` (`role_id`), PRIMARY KEY (`permission_id`, `role_id`)) ENGINE=InnoDB;
CREATE TABLE `user_user_role` (`role_id` varchar(36) NOT NULL, `user_id` varchar(36) NOT NULL, INDEX `IDX_c0c2bbb31e8e8708efc6dd5a64` (`role_id`), INDEX `IDX_beb8c39c852f4d132ba44b483c` (`user_id`), PRIMARY KEY (`role_id`, `user_id`)) ENGINE=InnoDB;
ALTER TABLE `permission_role_permission` ADD CONSTRAINT `FK_3247040996395a5faea3c9b3a54` FOREIGN KEY (`permission_id`) REFERENCES `permission_role`(`id`) ON DELETE CASCADE ON UPDATE NO ACTION;
ALTER TABLE `permission_role_permission` ADD CONSTRAINT `FK_7d9cfbfd027256ab08658bcf6e1` FOREIGN KEY (`role_id`) REFERENCES `permission_permission`(`id`) ON DELETE CASCADE ON UPDATE NO ACTION;
ALTER TABLE `user_user_role` ADD CONSTRAINT `FK_c0c2bbb31e8e8708efc6dd5a64b` FOREIGN KEY (`role_id`) REFERENCES `user_user`(`id`) ON DELETE CASCADE ON UPDATE NO ACTION;
ALTER TABLE `user_user_role` ADD CONSTRAINT `FK_beb8c39c852f4d132ba44b483c0` FOREIGN KEY (`user_id`) REFERENCES `permission_role`(`id`) ON DELETE CASCADE ON UPDATE NO ACTION;

Can anyone tell me why is schema:log detecting the changes in my entities, but migration:generate is not working?



Solution 1:[1]

For me this hint helped. Just run npm run build before generating with npm run typeorm -- migration:generate -n migration_name the new migration. Somehow an up to date dist folder needs to be present.

Solution 2:[2]

These are the steps that i took to make it work:

  1. Add an empty migration and on the up method add a query to drop all your tables.

Example:

await queryRunner.query(DROP TABLE "table_name");

  1. Remove this migration

  2. Remove your dist folder

  3. Remove your .idea folder

  4. Start your service - i used nest start (this should add a new and clean dist folder)

  5. Check your ormconfig.json file for your "migrations" location.

Mine was:

"migrations": [ "dist/database/migration/*.js" ]

  1. Check this path in the dist folder - i had no folder there with the name "migration".

  2. Add the folder migration (or use the name you have in the ormconfig.json)

  3. Run your migration:generate like before and it should work

(npm run typeorm -- migration:generate -n migration_name)

Hope it helped!

Solution 3:[3]

This problem appears when something wrong with paths. I have created a small working project using your configurations and directory style. Here is the link.
https://github.com/nairi-abgaryan/typeorm-mysql-nestjs

Quick overview. Updated the cli-configuration.ts file a little bit. The typeorm lib will use this configuration as you described in package.json.

import * as dotenv from 'dotenv';
import {TypeOrmModuleOptions} from '@nestjs/typeorm/dist/interfaces/typeorm-options.interface';
dotenv.config({
   path: '.env',
});

const config: TypeOrmModuleOptions = {
  type: 'mysql',
  host: process.env.TYPEORM_HOST,
  port: Number(process.env.TYPEORM_PORT),
  username: process.env.TYPEORM_USERNAME,
  password: process.env.TYPEORM_PASSWORD,
  database: process.env.TYPEORM_DATABASE,
  autoLoadEntities: true,
  entities: [`${__dirname}/../../../../src/**/*.entity{.ts,.js}`],
  migrations: [`${__dirname}/../../../migrations`],
  cli: {
    migrationsDir: `${__dirname}/../../../migrations`,
  },
  dropSchema: false,
};

export = config;

.env

TYPEORM_TYPE='mysql'
TYPEORM_HOST=localhost
TYPEORM_PORT=3306
TYPEORM_USERNAME='root'
TYPEORM_PASSWORD='root'
TYPEORM_DATABASE='myapp'
TYPEORM_MIGRATIONS='migrations'

Also, I created an ormconfig.json file which is for nest js connection to DB. As it says in the documentation when you don't want to config it in the app.module.

Note that the ormconfig.json file is loaded by the typeorm library. Thus, any of the extra properties described above (which are supported internally by way of the forRoot() method - for example, autoLoadEntities and retryDelay) won't be applied. Luckily, TypeORM provides the getConnectionOptions function that reads connection options from the ormconfig file or environment variables. With this, you can still use the configuration file and set Nest-specific options, as follows:

TypeOrmModule.forRootAsync({
  useFactory: async () =>
    Object.assign(await getConnectionOptions(), {
      autoLoadEntities: true,
    }),
});

Solution 4:[4]

We had a similar issue on projects with Nestjs + TypeORM + PostgreSQL.

We have found out that TypeORM had a conflict when you have an environment variable with the same value of type.

Check this example: https://imgur.com/a/pgR6OGJ

In this case, we have TYPEORM_TYPE = postgres and the type: 'postgres' for some unknown reason TypeORM cannot resolve and does not find your Database.

So to fix it try to remove it from your .env and try run again!

Hope I could help you or someone ;)

Solution 5:[5]

I was getting exactly the same thing and it seems that an older 0.2.x version is off. I've been using 0.2.34 and I was getting the issue there.

Moving to 0.2.45 fixed the issue for me.

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
Solution 2
Solution 3 Nairi Abgaryan
Solution 4 Felipe Lorenzoni
Solution 5 g_kou