-
Notifications
You must be signed in to change notification settings - Fork 46
Description
ProxyProviderNotResolvedException thrown even after resolveProxyProviders(...) inside cls.run(...)
Summary
We occasionally get ProxyProviderNotResolvedException when accessing a proxy provider, despite resolving it right before usage inside clsService.run(...).
This happens rarely and non-deterministically in production workers (BullMQ). It looks like a race between proxy resolution and access, or a context boundary issue.
Error
ProxyProviderNotResolvedException: Cannot access the property "getHash" on the Proxy provider UserSettingDocument because is has not been resolved yet and has been registered with the "strict: true" option. Make sure to call "await cls.resolveProxyProviders()" before accessing the Proxy provider.
at Function.create (/app/node_modules/nestjs-cls/dist/src/lib/proxy-provider/proxy-provider.exceptions.js:69:16)
at checkAllowedPropertyAccess (/app/node_modules/nestjs-cls/dist/src/lib/proxy-provider/proxy-provider-manager.js:180:81)
at Object.get (/app/node_modules/nestjs-cls/dist/src/lib/proxy-provider/proxy-provider-manager.js:119:51)
at QuestPrizeGeneratorWorker.resolveProxyProviders (/apps/meta-server/src/@job/common/job-worker.ts:46:59)
at processTicksAndRejections (node:internal/process/task_queues:95:5)
at QuestPrizeGeneratorWorker.prepareContext (/apps/meta-server/src/@job/common/context-job.worker.ts:24:5)
at QuestPrizeGeneratorWorker.execute (/apps/meta-server/src/@job/common/context-job.worker.ts:36:5)
at /app/node_modules/bullmq/src/classes/worker.ts:910:26
at Worker.retryIfFailed (/app/node_modules/bullmq/src/classes/worker.ts:1174:16)
What we do
@Injectable()
export class ExampleService {
constructor(
private readonly clsService: ClsService,
@Inject(UserSettingDocument) private readonly settingDocument: UserSettingDocument, // proxied provider
) {}
public example() {
return this.clsService.run(async () => {
await this.clsService.resolveProxyProviders([UserSettingDocument]);
// Rarely throws ProxyProviderNotResolvedException here:
this.settingDocument.getHash();
return true;
});
}
}Expected behavior
No exception is thrown after await clsService.resolveProxyProviders([...]) has completed within the same cls.run(...) scope.
Actual behavior
Very rarely (hard to reproduce locally), an exception is thrown saying the proxy has not been resolved yet. It happens in BullMQ worker jobs.
Environment
- nestjs-cls: 5.0.1
- NestJS: 10.3.5
- Node.js: 18.20.0
- Package manager: yarn 1.22.19
- Platform: BullMQ workers (separate process), Linux (Docker)
- BullMQ: 5.8.4
- strict mode:
strict: truefor proxy provider registration - cls setup:
ClsModule.forRoot({ global: true, middleware: { mount: true } }) - Repository type: monorepo (private)
Minimal reproduction (suggested outline)
I haven’t been able to produce a stable repro, but a flaky one could be:
- Start a BullMQ worker that wraps each job in
clsService.run(...). - Register a proxy provider with
strict: true. - Inside a job handler:
await cls.resolveProxyProviders([ProxyToken])await new Promise(r => setImmediate(r))(force a macro-task hop)- Access a method on the proxied provider.
Sometimes this still throws in our environment.
If there’s an official recommended pattern, I’m happy to test it and provide a full repro repo.
Workarounds tried
- Moving
resolveProxyProvidersearlier in the call chain — still happens. - Ensuring access happens synchronously right after resolve (reduced frequency but didn’t eliminate).
Thanks a lot! Happy to provide more logs or build a repro if you can point me to the right pattern to ensure context consistency.