Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IdentityMap Request Context fails in NestJS app when using app.setGlobalPrefix #130

Closed
belmeopmenieuwesim opened this issue Aug 3, 2023 · 7 comments

Comments

@belmeopmenieuwesim
Copy link

Describe the bug
When adding app.setGlobalPrefix('api'); to the bootstrap function in my NestJS main.ts file MikroORM does no longer properly handle request context for the identity map and it gives the error: Using global EntityManager instance methods for context specific actions is disallowed. The moment I remove app.setGlobalPrefix('api') everything works fine again.

Stack trace

[11:13:14 PM] File change detected. Starting incremental compilation...
2023-08-04 01:13:14 
2023-08-04 01:13:14 [11:13:14 PM] Found 0 errors. Watching for file changes.
2023-08-04 01:13:14 
2023-08-04 01:13:14 Debugger listening on ws://0.0.0.0:9229/51438209-c42b-4c53-bee1-0445a63b865e
2023-08-04 01:13:14 For help, see: https://nodejs.org/en/docs/inspector
2023-08-04 01:13:15 [Nest] 311  - 08/03/2023, 11:13:15 PM     LOG [NestFactory] Starting Nest application...
2023-08-04 01:13:15 [Nest] 311  - 08/03/2023, 11:13:15 PM     LOG [InstanceLoader] MikroOrmModule dependencies initialized +14ms
2023-08-04 01:13:15 [Nest] 311  - 08/03/2023, 11:13:15 PM     LOG [InstanceLoader] PassportModule dependencies initialized +0ms
2023-08-04 01:13:15 [Nest] 311  - 08/03/2023, 11:13:15 PM     LOG [InstanceLoader] JwtModule dependencies initialized +0ms
2023-08-04 01:13:15 [Nest] 311  - 08/03/2023, 11:13:15 PM     LOG [InstanceLoader] ConfigHostModule dependencies initialized +0ms
2023-08-04 01:13:15 [Nest] 311  - 08/03/2023, 11:13:15 PM     LOG [InstanceLoader] ConfigModule dependencies initialized +0ms
2023-08-04 01:13:15 [Nest] 311  - 08/03/2023, 11:13:15 PM     LOG [InstanceLoader] GraphQLSchemaBuilderModule dependencies initialized +2ms
2023-08-04 01:13:15 [Nest] 311  - 08/03/2023, 11:13:15 PM     LOG [InstanceLoader] GraphQLModule dependencies initialized +1ms
2023-08-04 01:13:15 [info] MikroORM version: 5.7.14
2023-08-04 01:13:15 [discovery] ORM entity discovery started, using TsMorphMetadataProvider
2023-08-04 01:13:15 [discovery] - processing 3 files
2023-08-04 01:13:15 [discovery] - processing entity User (/app/dist/src/user/user.entity.js)
2023-08-04 01:13:15 [discovery] - using cached metadata for entity User
2023-08-04 01:13:15 [discovery] - processing entity OrderItem (/app/dist/src/order/entities/order-item.entity.js)
2023-08-04 01:13:15 [discovery] - using cached metadata for entity OrderItem
2023-08-04 01:13:15 [discovery] - processing entity Order (/app/dist/src/order/entities/order.entity.js)
2023-08-04 01:13:15 [discovery] - using cached metadata for entity Order
2023-08-04 01:13:15 [discovery] - entity discovery finished, found 3 entities, took 29 ms
2023-08-04 01:13:15 [info] MikroORM successfully connected to database app on postgresql://postgres:*****@postgres:5432
2023-08-04 01:13:15 [query] select 1 from pg_database where datname = 'app' [took 1 ms, 1 result]
2023-08-04 01:13:15 [Nest] 311  - 08/03/2023, 11:13:15 PM     LOG [InstanceLoader] MikroOrmCoreModule dependencies initialized +49ms
2023-08-04 01:13:15 [Nest] 311  - 08/03/2023, 11:13:15 PM     LOG [InstanceLoader] MikroOrmModule dependencies initialized +0ms
2023-08-04 01:13:15 [Nest] 311  - 08/03/2023, 11:13:15 PM     LOG [InstanceLoader] AppModule dependencies initialized +1ms
2023-08-04 01:13:15 [Nest] 311  - 08/03/2023, 11:13:15 PM     LOG [InstanceLoader] OrderModule dependencies initialized +0ms
2023-08-04 01:13:15 [Nest] 311  - 08/03/2023, 11:13:15 PM     LOG [InstanceLoader] UserModule dependencies initialized +0ms
2023-08-04 01:13:15 [Nest] 311  - 08/03/2023, 11:13:15 PM     LOG [InstanceLoader] AuthModule dependencies initialized +0ms
2023-08-04 01:13:15 [Nest] 311  - 08/03/2023, 11:13:15 PM     LOG [RoutesResolver] AppController {/api}: +6ms
2023-08-04 01:13:15 [Nest] 311  - 08/03/2023, 11:13:15 PM     LOG [RouterExplorer] Mapped {/api, GET} route +1ms
2023-08-04 01:13:15 [Nest] 311  - 08/03/2023, 11:13:15 PM     LOG [RoutesResolver] AuthController {/api/auth}: +0ms
2023-08-04 01:13:15 [Nest] 311  - 08/03/2023, 11:13:15 PM     LOG [RouterExplorer] Mapped {/api/auth/login, POST} route +0ms
2023-08-04 01:13:15 [Nest] 311  - 08/03/2023, 11:13:15 PM     LOG [RouterExplorer] Mapped {/api/auth/protected, GET} route +0ms
2023-08-04 01:13:15 [Nest] 311  - 08/03/2023, 11:13:15 PM     LOG [GraphQLModule] Mapped {/graphql, POST} route +36ms
2023-08-04 01:13:15 [Nest] 311  - 08/03/2023, 11:13:15 PM     LOG [NestApplication] Nest application successfully started +1ms
2023-08-04 01:13:15 [Nest] 311  - 08/03/2023, 11:13:15 PM   ERROR [ExceptionsHandler] Using global EntityManager instance methods for context specific actions is disallowed. If you need to work with the global instance's identity map, use `allowGlobalContext` configuration option or `fork()` instead.
2023-08-04 01:13:15 ValidationError: Using global EntityManager instance methods for context specific actions is disallowed. If you need to work with the global instance's identity map, use `allowGlobalContext` configuration option or `fork()` instead.
2023-08-04 01:13:15     at Function.cannotUseGlobalContext (/app/node_modules/.pnpm/@mikro-orm+core@5.7.14_@mikro-orm+postgresql@5.7.14_@mikro-orm+seeder@5.7.14/node_modules/@mikro-orm/core/errors.js:95:16)
2023-08-04 01:13:15     at SqlEntityManager.getContext (/app/node_modules/.pnpm/@mikro-orm+core@5.7.14_@mikro-orm+postgresql@5.7.14_@mikro-orm+seeder@5.7.14/node_modules/@mikro-orm/core/EntityManager.js:1123:44)
2023-08-04 01:13:15     at SqlEntityManager.findOne (/app/node_modules/.pnpm/@mikro-orm+core@5.7.14_@mikro-orm+postgresql@5.7.14_@mikro-orm+seeder@5.7.14/node_modules/@mikro-orm/core/EntityManager.js:302:25)
2023-08-04 01:13:15     at AppController.index (/app/src/app.controller.ts:11:26)
2023-08-04 01:13:15     at /app/node_modules/.pnpm/@nestjs+core@10.1.2_@nestjs+common@10.1.2_@nestjs+platform-express@10.1.2_reflect-metadata@0.1.13_rxjs@7.8.1/node_modules/@nestjs/core/router/router-execution-context.js:38:29
2023-08-04 01:13:15     at InterceptorsConsumer.intercept (/app/node_modules/.pnpm/@nestjs+core@10.1.2_@nestjs+common@10.1.2_@nestjs+platform-express@10.1.2_reflect-metadata@0.1.13_rxjs@7.8.1/node_modules/@nestjs/core/interceptors/interceptors-consumer.js:12:20)
2023-08-04 01:13:15     at /app/node_modules/.pnpm/@nestjs+core@10.1.2_@nestjs+common@10.1.2_@nestjs+platform-express@10.1.2_reflect-metadata@0.1.13_rxjs@7.8.1/node_modules/@nestjs/core/router/router-execution-context.js:46:60
2023-08-04 01:13:15     at /app/node_modules/.pnpm/@nestjs+core@10.1.2_@nestjs+common@10.1.2_@nestjs+platform-express@10.1.2_reflect-metadata@0.1.13_rxjs@7.8.1/node_modules/@nestjs/core/router/router-proxy.js:9:23
2023-08-04 01:13:15     at Layer.handle [as handle_request] (/app/node_modules/.pnpm/express@4.18.2/node_modules/express/lib/router/layer.js:95:5)
2023-08-04 01:13:15     at next (/app/node_modules/.pnpm/express@4.18.2/node_modules/express/lib/router/route.js:144:13)

To Reproduce
Steps to reproduce the behavior:

  1. Setup a NestJS app with MikroORM installed
  2. Add app.setGlobalPrefix('api'); to the NestJS bootstrap function in main.ts
  3. Inject the EntityManager inside the AppController and call this.em.find(...) inside a route function of that controller.

Expected behavior
I would expect MikroORM to behave the same with and without using app.setGlobalPrefix.

Additional context
Using it within a NestJS application.

Versions
5.7.14

Dependency Version
node 20-slim
typescript 5.1.6
mikro-orm 5.7.14
nestjs 10.1.2
@B4nan B4nan transferred this issue from mikro-orm/mikro-orm Aug 4, 2023
@B4nan
Copy link
Member

B4nan commented Aug 4, 2023

This example app is doing that and works just fine. You will need to provide complete repro for this.

https://github.com/mikro-orm/nestjs-realworld-example-app/blob/master/src/main.ts#L8

@belmeopmenieuwesim
Copy link
Author

belmeopmenieuwesim commented Aug 4, 2023

@B4nan I cloned the realworld example app you linked and I managed to trigger the same bug. I found something interesting.

This AppController will work fine:

import { EntityManager } from '@mikro-orm/mysql';
import { Controller, Get } from '@nestjs/common';
import { Article } from './article/article.entity';

@Controller('api')
export class AppController {
  constructor(private em: EntityManager) {}

  @Get()
  async root() {
    let article = await this.em.find(Article, {});
    return article;
  }
}

Now if I change the @Controller() part by removing 'api', it no longer works and the bug is introduced:

import { EntityManager } from '@mikro-orm/mysql';
import { Controller, Get } from '@nestjs/common';
import { Article } from './article/article.entity';

@Controller()
export class AppController {
  constructor(private em: EntityManager) {}

  @Get()
  async root() {
    let article = await this.em.find(Article, {});
    return article;
  }
}

So conclusion is, for some reason, when the @Controller() and @Get() are both empty it will trigger the bug. Make either of them non-root and the bug goes away.

Here are the exact changes that will trigger the bug when navigating to http://localhost:3000/api:
belmeopmenieuwesim/nestjs-realworld-example-app@a223dd0

@bekkazy-k
Copy link

bekkazy-k commented Jan 2, 2024

I faced the same problem

it was a mistake
@Controller({ path: '', })

this is how the problem was solved
@Controller()

@B4nan
Copy link
Member

B4nan commented Jan 2, 2024

Probably related: nestjs/nest#11572

I can see that using /api fails but /api/ works as describer in nestjs/nest#11572 (comment)

@B4nan
Copy link
Member

B4nan commented Mar 18, 2024

Closing as this should be addressed in next nest version via nestjs/nest#13337

@B4nan B4nan closed this as completed Mar 18, 2024
@mlbonniec
Copy link

mlbonniec commented Mar 20, 2024

Closing as this should be addressed in next nest version via nestjs/nest#13337

Unfortunately it didn't fix the issue.

The error is still present when using setGlobalPrefix()

ValidationError: Using global EntityManager instance methods for context specific actions is disallowed. If you need to work with the global instance's identity map, use allowGlobalContext configuration option or fork() instead.

@B4nan
Copy link
Member

B4nan commented Mar 20, 2024

Yeah I am aware of that, still it doesnt change the fact that this is a bug in nest.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants