Skip to Content
ErrorsNEXUS_LOADED_AFTER_SCOPE

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_LOADED_AFTER_SCOPE

NEXUS_LOADED_AFTER_SCOPE means a scope was asked for a token from a module that ship.load() added after the scope was created. A scope resolves against the graph current at its creation. get() on the scope throws it directly, and so does resolve(), also for a lazy() entry.

Reproduce NEXUS_LOADED_AFTER_SCOPE

The region creates a shuttle, loads Survey, and asks the shuttle for NavCharts. 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 type { Scope } from '@nexusdi/core'; import { errors } from '@nexusdi/errors'; interface INavCharts { plot(to: string): string; } const NAV_CHARTS = new Token<INavCharts>('NavCharts'); class StarCharts implements INavCharts { plot(to: string) { return `course to ${to}`; } } const Survey = defineModule({ name: 'Survey', providers: [provide(NAV_CHARTS, { useClass: StarCharts })], exports: [NAV_CHARTS], }); const Meridian = defineModule({ name: 'Meridian' }); const getCharts = (shuttle: Scope) => { try { return shuttle.get(NAV_CHARTS); } catch (error) { return error; } }; await using ship = await Nexus.create(Meridian); await using shuttle = await ship.createScope(); await ship.load(Survey); const thin = getCharts(shuttle); const line = isNexusError(thin) ? thin.message : null; // -> '[NEXUS_LOADED_AFTER_SCOPE] token=NavCharts module=Survey. https://nexus.js.org/errors/NEXUS_LOADED_AFTER_SCOPE' console.log(line); await using fullShip = await Nexus.create(Meridian, { plugins: [errors()] }); await using fullShuttle = await fullShip.createScope(); await fullShip.load(Survey); const full = getCharts(fullShuttle); const text = isNexusError(full) ? full.message.split('\n') : null; // -> ['[NEXUS_LOADED_AFTER_SCOPE] NavCharts comes from Survey, which was loaded after this scope was created. A scope resolves against the graph current at its creation.', ' Fix: call await scope.extend() after load(), or create a new scope.'] 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. The module field names Survey. Then save the fix region below as fixed.ts and run npx tsx fixed.ts. It prints course to Kepler-442b.

Fix NEXUS_LOADED_AFTER_SCOPE

NEXUS_LOADED_AFTER_SCOPE is fixed by calling await scope.extend() after load(), which moves the scope to the current graph and builds the scoped factories the loaded modules add, or by creating a new scope. extend() throws NEXUS_REQUEST_MISSING when a loaded module adds a REQUEST dependent and the scope has no request. Scopes and the REQUEST Token covers scopes.

import { Nexus, Token, defineModule, provide } from '@nexusdi/core'; interface INavCharts { plot(to: string): string; } const NAV_CHARTS = new Token<INavCharts>('NavCharts'); class StarCharts implements INavCharts { plot(to: string) { return `course to ${to}`; } } const Survey = defineModule({ name: 'Survey', providers: [provide(NAV_CHARTS, { useClass: StarCharts })], exports: [NAV_CHARTS], }); await using ship = await Nexus.create(defineModule({ name: 'Meridian' })); await using shuttle = await ship.createScope(); await ship.load(Survey); await shuttle.extend(); const course = shuttle.get(NAV_CHARTS).plot('Kepler-442b'); // -> 'course to Kepler-442b' console.log(course);

Try it: delete the await shuttle.extend(); line from fixed.ts and run it again. tsc accepts the file. tsx throws an uncaught LoadedAfterScopeError that starts with [NEXUS_LOADED_AFTER_SCOPE] token=NavCharts module=Survey.. Put the line back and the program prints course to Kepler-442b again.

Fields of LoadedAfterScopeError

LoadedAfterScopeError carries these fields:

  • token: the display name of the token asked for.
  • module: the module that provides it.
  • entry: the deps entry of resolve() this error is about, deps.<key> for the key of an object, such as deps.charts, or deps[0] for a tuple, and null for get().