Skip to Content
ErrorsNEXUS_PLUGIN_INVALID

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_PLUGIN_INVALID

NEXUS_PLUGIN_INVALID means a plugin passed to Nexus.create or Nexus.check is malformed: plugins is not an array, an entry is not an object, a plugin has no name or the name of an earlier plugin, or a hook has the wrong type. Core validates every plugin before it compiles anything and reports each fault inside NEXUS_BLUEPRINT_INVALID. Nexus.create rejects with that error and Nexus.check throws it. No call raises NEXUS_PLUGIN_INVALID bare, and the reason field says which fault it is.

Reproduce NEXUS_PLUGIN_INVALID

The region registers a plugin with an empty name. 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. The full text counts positions with errors() included, so it names plugins[1].

import { NEXUS_PLUGIN_API, Nexus, Token, isNexusError } from '@nexusdi/core'; import { provide } from '@nexusdi/core'; import type { NexusPlugin } from '@nexusdi/core'; import { errors } from '@nexusdi/errors'; interface IReactorCore { readonly output: number; } const REACTOR = new Token<IReactorCore>('ReactorCore'); class FusionReactor implements IReactorCore { readonly output = 1.21; } const providers = [provide(REACTOR, { useClass: FusionReactor })]; // A plugin needs a non-empty name. const cache: NexusPlugin = { name: '', apiVersion: NEXUS_PLUGIN_API }; const startup = (plugins: NexusPlugin[]) => Nexus.create(providers, { plugins }).catch((error: unknown) => error); const thin = await startup([cache]); if (!isNexusError(thin, 'NEXUS_BLUEPRINT_INVALID')) throw thin; const first = thin.errors[0]; const line = first?.message; // -> '[NEXUS_PLUGIN_INVALID] plugin=plugins[0] reason=no-name. https://nexus.js.org/errors/NEXUS_PLUGIN_INVALID' console.log(line); if (!isNexusError(first, 'NEXUS_PLUGIN_INVALID')) throw first; const reason = first.reason; // -> 'no-name' console.log(reason); const full = await startup([errors(), cache]); if (!isNexusError(full, 'NEXUS_BLUEPRINT_INVALID')) throw full; const text = full.errors[0]?.message; // -> '[NEXUS_PLUGIN_INVALID] plugins[1] has no name; set name to a non-empty string.' console.log(text);

Try it: save the region as error.ts and run npx tsx error.ts. It prints three lines: the one-line message, which names plugins[0], then no-name, the reason field, then the full text, [NEXUS_PLUGIN_INVALID] plugins[1] has no name; set name to a non-empty string., with no fix line. Then save the fix region below as fixed.ts and run npx tsx fixed.ts. It prints 1.21 1: the reactor output, then the number of construct events the plugin saw.

Fix NEXUS_PLUGIN_INVALID

NEXUS_PLUGIN_INVALID is fixed by correcting the plugin the reason names. A plugin is an object with a unique, non-empty name and the apiVersion it was written for. Every hook is optional and has the documented type. A compile member is an object of hook functions, and modules is an array. onInit takes only the value false. NexusDI Plugins covers registration.

import { NEXUS_PLUGIN_API, Nexus, Token, provide } from '@nexusdi/core'; import type { NexusPlugin } from '@nexusdi/core'; interface IReactorCore { readonly output: number; } const REACTOR = new Token<IReactorCore>('ReactorCore'); class FusionReactor implements IReactorCore { readonly output = 1.21; } let built = 0; const cache: NexusPlugin = { name: 'acme:cache', apiVersion: NEXUS_PLUGIN_API, observe(event) { if (event.type === 'construct') built++; }, }; await using ship = await Nexus.create( [provide(REACTOR, { useClass: FusionReactor })], { plugins: [cache] }, ); const output = ship.get(REACTOR).output; // -> 1.21 console.log(output, built);

Try it: in fixed.ts, change 'acme:cache' to '' and run it again. tsc accepts the file, because name is a string. tsx throws an uncaught BlueprintError whose second line is [NEXUS_PLUGIN_INVALID] plugin=plugins[0] reason=no-name. followed by the address of this page. Change the name back and the program prints 1.21 1 again.

Fields of PluginError

PluginError carries the fields of all four plugin codes. A field the code does not use is null or empty.

  • plugin: the plugin’s name, or its position such as plugins[0] when it has no name or is not an object. It is plugins when the option is not an array. null for NEXUS_PLUGIN_CONFLICT.
  • reason: for NEXUS_PLUGIN_INVALID: not-an-array, not-an-object, no-name, duplicate-name, bad-hook, bad-compile, bad-modules or bad-on-init. null for the other codes.
  • detail: for NEXUS_PLUGIN_INVALID: an array of strings that names the value (not-an-array, not-an-object and bad-on-init) or the hook key (bad-hook). Empty for every other reason and code.
  • apiVersion: for NEXUS_PLUGIN_VERSION: the version the plugin declares, as a string such as '2', or 'undefined' when it declares none.
  • supported: for NEXUS_PLUGIN_VERSION: the plugin API versions this core supports, as an array of numbers. It holds [1] in 0.4.
  • plugins: for NEXUS_PLUGIN_CONFLICT: the names of the first plugin that rewrote the definition and the later one that rewrote it again.
  • target: for NEXUS_PLUGIN_CONFLICT: the name of the module or provider both rewrite.
  • hook: for NEXUS_PLUGIN_FAILED: the hook that failed, one of setup, tokenKey, construct, compile.module, compile.provider and compile.check.
  • disposalErrors: for NEXUS_PLUGIN_FAILED: the errors thrown while disposing what create had built, as an array. It is empty unless a setup failure closed the container.