Skip to Content
ErrorsNEXUS_AMBIGUOUS_PROVIDER

This page documents the 0.4 release candidates of @nexusdi/core. The newest on npm is 0.4.0-rc.1. The documentation for 0.3.2, the current release, is at nexus.js.org. Try the release candidate.

NEXUS_AMBIGUOUS_PROVIDER

NEXUS_AMBIGUOUS_PROVIDER means a module imports two or more modules that each export their own provider of one token, so the module cannot tell which one to use. Nexus.create reports it inside NEXUS_BLUEPRINT_INVALID.

Reproduce NEXUS_AMBIGUOUS_PROVIDER

The region has Comms export a SubspaceRelay and Lasers export a LaserLink, both under SubspaceLink, and Tactical imports both. Without a plugin, core prints a one-line message that starts with the code and ends with the address of this page. With errors() from @nexusdi/errors registered (npm install @nexusdi/errors@next), the same error carries the full text and its fix.

import { Nexus, Token, defineModule, isNexusError } from '@nexusdi/core'; import { provide } from '@nexusdi/core'; import { errors } from '@nexusdi/errors'; interface ISubspaceLink { readonly frequency: number; } const SUBSPACE_LINK = new Token<ISubspaceLink>('SubspaceLink'); class SubspaceRelay implements ISubspaceLink { readonly frequency = 1420; } class LaserLink implements ISubspaceLink { readonly frequency = 1701; } const Comms = defineModule({ name: 'Comms', providers: [provide(SUBSPACE_LINK, { useClass: SubspaceRelay })], exports: [SUBSPACE_LINK], }); const Lasers = defineModule({ name: 'Lasers', providers: [provide(SUBSPACE_LINK, { useClass: LaserLink })], exports: [SUBSPACE_LINK], }); const Tactical = defineModule({ name: 'Tactical', imports: [Comms, Lasers] }); const thin = await Nexus.create(Tactical).catch((error: unknown) => error); if (!isNexusError(thin, 'NEXUS_BLUEPRINT_INVALID')) throw thin; const line = thin.errors[0]?.message; // -> '[NEXUS_AMBIGUOUS_PROVIDER] token=SubspaceLink module=Tactical candidates=Comms,Lasers. https://nexus.js.org/errors/NEXUS_AMBIGUOUS_PROVIDER' console.log(line); const full = await Nexus.create(Tactical, { plugins: [errors()] }).catch( (error: unknown) => error, ); if (!isNexusError(full, 'NEXUS_BLUEPRINT_INVALID')) throw full; const text = full.errors[0]?.message.split('\n'); // -> ['[NEXUS_AMBIGUOUS_PROVIDER] Tactical sees SubspaceLink from Comms and Lasers, and they provide different instances.', ' Fix: export SubspaceLink from one of them only, or provide SubspaceLink in Tactical, which shadows the imports.'] console.log(text);

Try it: save the region as error.ts and run npx tsx error.ts. The one-line message ends its fields with candidates=Comms,Lasers, which names both modules. The full text adds the two ways out. Then save the fix region below as fixed.ts and run npx tsx fixed.ts. It prints 1701.

Fix NEXUS_AMBIGUOUS_PROVIDER

NEXUS_AMBIGUOUS_PROVIDER is fixed by leaving one provider of the token visible to the importing module: export the token from one of the modules only, or provide the token in the importing module, which shadows the imports. To pick an implementation by configuration, give one configurable module a factory that chooses between them (see Configurable Modules). Here Tactical imports Lasers alone.

import { Nexus, Token, defineModule, provide } from '@nexusdi/core'; interface ISubspaceLink { readonly frequency: number; } const SUBSPACE_LINK = new Token<ISubspaceLink>('SubspaceLink'); class LaserLink implements ISubspaceLink { readonly frequency = 1701; } const Lasers = defineModule({ name: 'Lasers', providers: [provide(SUBSPACE_LINK, { useClass: LaserLink })], exports: [SUBSPACE_LINK], }); const Tactical = defineModule({ name: 'Tactical', imports: [Lasers] }); await using ship = await Nexus.create(Tactical); const frequency = ship.get(SUBSPACE_LINK).frequency; // -> 1701 console.log(frequency);

Try it: in error.ts, add providers: [provide(SUBSPACE_LINK, { useClass: LaserLink })] to Tactical. Then replace everything from the thin line down with await using ship = await Nexus.create(Tactical); and console.log(ship.get(SUBSPACE_LINK).frequency);. Nexus.create resolves and the program prints 1701, because the provider in Tactical shadows both imports. Take the providers line out again and the error returns.

Fields of AmbiguousProviderError

AmbiguousProviderError carries these fields:

  • token: the display name of the token.
  • module: the module that sees several providers.
  • candidates: the names of the imported modules that export a provider of the token.