Skip to Content
ErrorsNEXUS_LAZY_ASYNC

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_LAZY_ASYNC

NEXUS_LAZY_ASYNC means a provider with eager: false was built on demand, and its factory returned a promise, or the onInit of its singleton instance did. get() cannot wait for a promise, so it throws. get(), resolve(), the get() of a scope for a scoped factory and a lazy() thunk throw it directly, also when the request reaches the provider through the dependencies of another eager: false provider. The container stores nothing, so the next request builds again and throws again.

Reproduce NEXUS_LAZY_ASYNC

TypeScript rejects eager: false on an async factory and on a class whose onInit returns a promise. It reports TS2769 on the provide( call, and the error for the matching overload names this code:

Fails the type check

provide(NAV_CHARTS, { useFactory: async () => charts, eager: false }); // TS2769: No overload matches this call. The error for the factory overload ends with: // Type 'false' is not assignable to type 'true | "NEXUS_LAZY_ASYNC: an async provider is built during create or createScope, so it cannot be eager: false. Remove eager: false, or make the token a function type and provide () => Promise<T>" | undefined'.

The error reaches run time when the types cannot see the promise. The region uses a JavaScript helper whose typings say it returns charts. 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 INavCharts { plot(to: string): string; } const NAV_CHARTS = new Token<INavCharts>('NavCharts'); // downloadCharts stands in for a JavaScript helper whose typings say it // returns charts. At run time it returns a promise, which TypeScript cannot see. const downloadCharts = (async () => ({ plot: (to: string) => `course to ${to}`, })) as unknown as () => INavCharts; const Tactical = defineModule({ name: 'Tactical', providers: [ provide(NAV_CHARTS, { useFactory: () => downloadCharts(), eager: false }), ], exports: [NAV_CHARTS], }); const getCharts = (ship: Nexus) => { try { return ship.get(NAV_CHARTS); } catch (error) { return error; } }; await using ship = await Nexus.create(Tactical); const thin = getCharts(ship); const line = isNexusError(thin) ? thin.message : null; // -> '[NEXUS_LAZY_ASYNC] token=NavCharts module=Tactical. https://nexus.js.org/errors/NEXUS_LAZY_ASYNC' console.log(line); await using fullShip = await Nexus.create(Tactical, { plugins: [errors()] }); const full = getCharts(fullShip); const text = isNexusError(full) ? full.message.split('\n') : null; // -> ['[NEXUS_LAZY_ASYNC] NavCharts (module Tactical) is eager: false and its build returned a promise; get() cannot wait for it.', ' Fix: remove eager: false, or make the token a function type and provide () => Promise<T>.'] console.log(text);

Try it: save the region as error.ts and run npx tsx error.ts. It prints the one-line message, then the full text as an array of two strings. Then save the fix region below as fixed.ts and run npx tsx fixed.ts. It prints course to Kepler-442b.

Fix NEXUS_LAZY_ASYNC

NEXUS_LAZY_ASYNC is fixed by removing eager: false from an async provider, so create awaits it. Alternatively, make the token a function type and provide () => Promise<T>.

import { Nexus, Token, defineModule, provide } from '@nexusdi/core'; interface INavCharts { plot(to: string): string; } const NAV_CHARTS = new Token<INavCharts>('NavCharts'); async function downloadCharts(): Promise<INavCharts> { return { plot: (to) => `course to ${to}` }; } const Tactical = defineModule({ name: 'Tactical', providers: [provide(NAV_CHARTS, { useFactory: downloadCharts })], exports: [NAV_CHARTS], }); await using ship = await Nexus.create(Tactical); const course = ship.get(NAV_CHARTS).plot('Kepler-442b'); // -> 'course to Kepler-442b' console.log(course);

Try it: in fixed.ts, add eager: false to the options of provide(NAV_CHARTS, ...) and run it again. tsc reports TS2769 on the provide( call, with the message shown above. tsx skips the type check, and ship.get(NAV_CHARTS) throws an uncaught LazyAsyncError that starts with [NEXUS_LAZY_ASYNC] token=NavCharts module=Tactical.. Remove eager: false and the program prints course to Kepler-442b again.

Fields of LazyAsyncError

LazyAsyncError carries these fields:

  • token: the display name of the provider.
  • module: its module.