typeorm-transactional icon indicating copy to clipboard operation
typeorm-transactional copied to clipboard

Error: DataSource with name "default" has already added

Open piszczu4 opened this issue 1 year ago • 4 comments

I've got an error from title when trying to deploy app with some migrations. This is my app.module:

 TypeOrmModule.forRootAsync({
      imports: [ConfigModule],
      useFactory: (configService: ConfigService<IConfiguration>) => {
        const databaseConfig = configService.get('database', { infer: true });
        return {
          type: databaseConfig.type as any,
          host: databaseConfig.host,
          port: databaseConfig.port,
          username: databaseConfig.username,
          password: databaseConfig.password,
          database: databaseConfig.name,
          synchronize: false,
          subscribers: [BoughtCourseSubscriber, CourseNodeSubscriber, BoughtHomeworkSubscriber],
          entities: [__dirname + '/modules/**/*.entity.{js,ts}'],
          migrations: [__dirname + '/migrations/*.{js,ts}'],
          migrationsRun: true,
          cli: {
            migrationsDir: __dirname + '/migrations',
          },
          ...(!databaseConfig.sslRejectUnathorized
            ? {
                ssl: {
                  rejectUnauthorized: false,
                },
              }
            : {}),
        };
      },
      async dataSourceFactory(options) {
        if (!options) {
          throw new Error('Invalid options passed');
        }

        const dataSource = new DataSource(options);
        return addTransactionalDataSource(dataSource);
      },
      inject: [ConfigService],
    }),

Any ideas why is that a case? Here is full error stack:

[2024-08-28 21:13:56] Error: DataSource with name "default" has already added.
[2024-08-28 21:13:56]     at addTransactionalDataSource (/workspace/node_modules/typeorm-transactional/dist/common/index.js:156:15)
[2024-08-28 21:13:56]     at dataSourceFactory (/workspace/dist/src/app.module.js:99:83)
[2024-08-28 21:13:56]     at /workspace/node_modules/@nestjs/typeorm/dist/typeorm-core.module.js:169:36
[2024-08-28 21:13:56]     at Observable._subscribe (/workspace/node_modules/rxjs/dist/cjs/internal/observable/defer.js:8:31)
[2024-08-28 21:13:56]     at Observable._trySubscribe (/workspace/node_modules/rxjs/dist/cjs/internal/Observable.js:41:25)
[2024-08-28 21:13:56]     at /workspace/node_modules/rxjs/dist/cjs/internal/Observable.js:35:31
[2024-08-28 21:13:56]     at Object.errorContext (/workspace/node_modules/rxjs/dist/cjs/internal/util/errorContext.js:22:9)
[2024-08-28 21:13:56]     at Observable.subscribe (/workspace/node_modules/rxjs/dist/cjs/internal/Observable.js:26:24)
[2024-08-28 21:13:56]     at subscribeForRetryWhen (/workspace/node_modules/rxjs/dist/cjs/internal/operators/retryWhen.js:14:31)
[2024-08-28 21:13:56]     at /workspace/node_modules/rxjs/dist/cjs/internal/operators/retryWhen.js:18:43

piszczu4 avatar Aug 28 '24 21:08 piszczu4

Any ideas? It works only when there is no migrations

piszczu4 avatar Sep 03 '24 00:09 piszczu4

Same problem here.

asf-loft avatar Sep 19 '24 18:09 asf-loft

Same problem here.

I did the following and it seems that it works:

async dataSourceFactory(options) {
    const dataSource = await new DataSource(options).initialize();
    return addTransactionalDataSource(dataSource);
  },

piszczu4 avatar Sep 20 '24 02:09 piszczu4

So here's a way that I fixed this:

    dataSourceFactory: (options) => {
        const dataSource = new DataSource(options);

        // This is safe to do. We need to delete the previously registered dataSource
        // inside typeorm-transactional because typeorm might retry if it fails to connect, which
        // will create a new DataSource to use. Typeorm-transactional however doesn't allow overriding
        // the existing registration with a new one, so we need to delete the old registration first.
        // This fixes the error: "DataSource with name "default" has already added." we occasionally see.
        deleteDataSourceByName('default');
        return Promise.resolve(addTransactionalDataSource(dataSource));
    },

hongha912 avatar May 16 '25 14:05 hongha912