question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Unable to resolve dependencies of RabbitMQModule

See original GitHub issue

Hi, I have created a core lib for my project which imports the RabbitMQModule, configures it and makes it available to downstream services.

I’m running this version:

    "@golevelup/nestjs-rabbitmq": "^3.1.0",

The module looks like this:

import { Global, Module, DynamicModule } from '@nestjs/common';
import { RabbitMQModule } from '@golevelup/nestjs-rabbitmq';

// internal
import { AmqpService } from './services';
import { AmqpOptions, RABBITMQ_SERVICE_NAME } from './config';
import { AmqpExchange } from './enums';

@Global()
@Module({})
export class AmqpModule {
  static forRoot(options: AmqpOptions): DynamicModule {
    const module: DynamicModule = {
      global: true,
      module: AmqpModule,
      providers: [AmqpService],
      imports: [],
      exports: [AmqpService]
    };

    module.imports.push(
      RabbitMQModule.forRoot(RabbitMQModule, {
          ...options,
          exchanges: [
              ...(options.exchanges || []),
              {
                  name: AmqpExchange.EVT,
                  type: 'topic',
              },
          ],
          connectionInitOptions: {
              ...(options.connectionInitOptions || {}),
              wait: true,
          },
          enableControllerDiscovery: true
      }),
      AmqpModule
    );

    module.providers.push({
      provide: RABBITMQ_SERVICE_NAME, // used to identify the service across the microservices
      useValue: options.service_name,
    });

    return module;
  }
}

my service looks like this:

import { Injectable, Inject } from '@nestjs/common';
import { AmqpConnection } from '@golevelup/nestjs-rabbitmq';

import {
  AmqpExchange,
  AmqpQueueDirection,
  TseAction,
} from "../enums";
import {
  TseEntity,
  TseEvent,
} from '../interfaces';
import { RABBITMQ_SERVICE_NAME } from '../config';

@Injectable()
export class AmqpService {
  constructor(
    private amqpConnection: AmqpConnection,
    @Inject(RABBITMQ_SERVICE_NAME)
    private ServiceName: string,
  ) {
  }

  // logs missing amqp connection in case injection fails
  amqp(): AmqpConnection {
    if (this.amqpConnection) return this.amqpConnection;

    // REVIEW: https://github.com/golevelup/nestjs/issues/430
    // Must pin v2.2.0
    console.error(
      'AmqpModule: AMQP provider is null in config, but service is initialized - verify @golevelup/nestjs-rabbitmq npm package is on v2.2.0',
    );
  }

  /**
   * This method will serve as a common wrapper for creating new technical system events in the system
   * @param name
   * @param action
   * @param entity
   * @param content
   */
  public async TSE<T>(
    name: string,
    action: TseAction | string,
    entity: TseEntity,
    content: T,
  ) {
    try {
      await this.TseInternal<T>({
        Entity: entity,
        Content: content,
        RoutingKey: `${this.ServiceName}.${name}.${action}`,
        Exchange: AmqpExchange.EVT,
        CreatedAt: new Date(),
      });
    } catch (e) {
      console.error('Unable to publish TSE', e);
    }
  }

  private async TseInternal<T>(e: TseEvent<T>) {
    await this.amqp().publish(e.Exchange, e.RoutingKey, e);
  }
}

export function QueueName(
  service: string,
  direction: AmqpQueueDirection,
  disambiguator?: string,
) {
  if (disambiguator) return `${service}.${direction}.${disambiguator}`;

  return `${service}.${direction}`;
}

I followed the documentation provided to initialize it but I’m running into a bit of an issue getting the project running I’m facing this error message:

[Nest] 31779  - 07/24/2022, 11:57:28 AM   ERROR [ExceptionHandler] Nest can't resolve dependencies of the RabbitMQModule (DiscoveryService, ?, RabbitRpcParamsFactory, AmqpConnectionManager). Please make sure that the argument ExternalContextCreator at index [1] is available in the RabbitMQModule context.

Potential solutions:
- If ExternalContextCreator is a provider, is it part of the current RabbitMQModule?
- If ExternalContextCreator is exported from a separate @Module, is that module imported within RabbitMQModule?
  @Module({
    imports: [ /* the Module containing ExternalContextCreator */ ]
  })

Error: Nest can't resolve dependencies of the RabbitMQModule (DiscoveryService, ?, RabbitRpcParamsFactory, AmqpConnectionManager). Please make sure that the argument ExternalContextCreator at index [1] is available in the RabbitMQModule context.

Potential solutions:
- If ExternalContextCreator is a provider, is it part of the current RabbitMQModule?
- If ExternalContextCreator is exported from a separate @Module, is that module imported within RabbitMQModule?
  @Module({
    imports: [ /* the Module containing ExternalContextCreator */ ]
  })

    at Injector.lookupComponentInParentModules (/Users/kom/Projects/DriverFly/driverfly-backend/node_modules/@nestjs/core/injector/injector.js:231:19)
    at Injector.resolveComponentInstance (/Users/kom/Projects/DriverFly/driverfly-backend/node_modules/@nestjs/core/injector/injector.js:184:33)
    at resolveParam (/Users/kom/Projects/DriverFly/driverfly-backend/node_modules/@nestjs/core/injector/injector.js:106:38)
    at async Promise.all (index 1)
    at Injector.resolveConstructorParams (/Users/kom/Projects/DriverFly/driverfly-backend/node_modules/@nestjs/core/injector/injector.js:121:27)
    at Injector.loadInstance (/Users/kom/Projects/DriverFly/driverfly-backend/node_modules/@nestjs/core/injector/injector.js:52:9)
    at Injector.loadProvider (/Users/kom/Projects/DriverFly/driverfly-backend/node_modules/@nestjs/core/injector/injector.js:74:9)
    at async Promise.all (index 0)
    at InstanceLoader.createInstancesOfProviders (/Users/kom/Projects/DriverFly/driverfly-backend/node_modules/@nestjs/core/injector/instance-loader.js:44:9)
    at /Users/kom/Projects/DriverFly/driverfly-backend/node_modules/@nestjs/core/injector/instance-loader.js:29:13
    at async Promise.all (index 8)
    at InstanceLoader.createInstances (/Users/kom/Projects/DriverFly/driverfly-backend/node_modules/@nestjs/core/injector/instance-loader.js:28:9)
    at InstanceLoader.createInstancesOfDependencies (/Users/kom/Projects/DriverFly/driverfly-backend/node_modules/@nestjs/core/injector/instance-loader.js:18:9)
    at /Users/kom/Projects/DriverFly/driverfly-backend/node_modules/@nestjs/core/nest-factory.js:96:17
    at Function.asyncRun (/Users/kom/Projects/DriverFly/driverfly-backend/node_modules/@nestjs/core/errors/exceptions-zone.js:22:13)
    at NestFactoryStatic.initialize (/Users/kom/Projects/DriverFly/driverfly-backend/node_modules/@nestjs/core/nest-factory.js:94:13)
    at NestFactoryStatic.create (/Users/kom/Projects/DriverFly/driverfly-backend/node_modules/@nestjs/core/nest-factory.js:37:9)
    at bootstrap (/Users/kom/Projects/DriverFly/driverfly-backend/src/main.ts:28:15)

Any ideas what I might be doing incorrectly here ?

Issue Analytics

  • State:open
  • Created a year ago
  • Reactions:1
  • Comments:5 (1 by maintainers)

github_iconTop GitHub Comments

2reactions
buffcodecommented, Sep 23, 2022

I have the same error when using the library with PNPM / monorepos.

@golevelup/nestjs-rabbitmq uses ExternalContextCreator from @nestjs/core but does not define it as its own dependency. As such it is not available directly and fails when being build.

I was able to verify that using pnpm patch/patch-commit and adding the following to @golevelup/nestjs-rabbitmq@3.2.0 package.json:

  "dependencies": {
    // ...
    "@nestjs/core": "^9.0.5"
  },

IMHO this is flaw, a library should always be explicit about the dependencies it uses directly, but currently @nestjs/... dependencies are used directy without specifying them.

1reaction
kn327commented, Aug 2, 2022

@underfisk , The nestjs versions were identical and I am running v8 for the common. Here are the package versions I’m using

    "@golevelup/nestjs-rabbitmq": "^3.1.0",
    "@nestjs/common": "^8.4.7",

I was able to get a workaround for the issue by creating a custom provider for the AMQP connection which appears to work correctly:

    module.providers.push({
      provide: AmqpConnection,
      useFactory: async () => {
        const connection = new AmqpConnection(options);

        await connection.init();

        return connection;
      },
    });

I noticed the issue only happens when I try to create a global module wrapper as a sub-module of a sub-module. My architecture is as follows:

  • AppRootModule (the microservice running the application) ** ServiceModule1 (some sub-service of the microservice) ** …Other various microservice-specific modules ** DomainCommonModule (A common module initializing all public services shared by all of my microservices) - exported as global *** AmqpModule (my wrapper for the go-level-up rabbitMQ Module) - exported as global *** …Other various common modules - exported as global

If I initialize the AmqpModule directly in ServiceModule1 which needs it, there is no problem. However, if I initialize the AmqpModule in either the AppRootModule or the DomainCommonModule, the dependency problem occurs

Read more comments on GitHub >

github_iconTop Results From Across the Web

Nest can't resolve dependencies of RabbitMQService service
The error I am getting is: Nest can't resolve dependencies of the RabbitMQService (?). Please make sure that the argument rabbitmq at index...
Read more >
Can not resolve dependencies · Issue #26 · nestjsx/nestjs-amqp
I tried to send a message, like described here, but I'm getting the following error: [ExceptionHandler] Nest can't resolve dependencies of ...
Read more >
Common errors - FAQ - A progressive Node.js framework
"Cannot resolve dependency" error. The most common culprit of the error, is not having the <provider> in the module's providers array. Please make...
Read more >
Cluster Formation and Peer Discovery - RabbitMQ
A node with configuration settings that belong a non-enabled peer discovery plugin will fail to start and report those settings as unknown.
Read more >
Command Line Tools - RabbitMQ
rabbitmqadmin is a standalone tool (no dependencies other than Python 3) that ... When a CLI tool such as rabbitmqctl fails to authenticate...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found