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_FAILED
NEXUS_PLUGIN_FAILED means a plugin’s hook threw, or returned a value of the wrong type. The hook’s error is its cause, and the hook field names the hook. Where the error surfaces depends on the hook:
- A
setuphook that throws or rejects makesNexus.createreject withNEXUS_PLUGIN_FAILEDbare, after disposing what it built.disposalErrorsholds what that disposal threw. - A hook under
compilethat throws or returns the wrong type, and atokenKeyhook that throws during a compile, is reported inside NEXUS_BLUEPRINT_INVALID.Nexus.createandload()reject with it andNexus.checkthrows it. - A
tokenKeyhook that throws for a token it meets makes the call throwNEXUS_PLUGIN_FAILEDbare. That holds forget(),has(),resolve()andvalidate()on the container, and for the same calls on a scope, which has novalidate(). - A
constructhook that throws, or returns a thenable, makes the build fail with NEXUS_PROVIDER_FAILED.NEXUS_PLUGIN_FAILEDis itscause, and the hook’s own error is thecauseof that.
A throw from an observe or a dispose hook does not use this code.
Reproduce NEXUS_PLUGIN_FAILED
The region registers a plugin whose setup hook throws. 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.
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 })];
// The setup hook throws, so create rejects.
const cache: NexusPlugin = {
name: 'acme:cache',
apiVersion: NEXUS_PLUGIN_API,
setup() {
throw new Error('cache store offline');
},
};
const startup = (plugins: NexusPlugin[]) =>
Nexus.create(providers, { plugins }).catch((error: unknown) => error);
const thin = await startup([cache]);
if (!isNexusError(thin, 'NEXUS_PLUGIN_FAILED')) throw thin;
const line = thin.message; // -> '[NEXUS_PLUGIN_FAILED] plugin=acme:cache hook=setup. https://nexus.js.org/errors/NEXUS_PLUGIN_FAILED'
console.log(line);
const hook = thin.hook; // -> 'setup'
console.log(hook);
const cause = String(thin.cause); // -> 'Error: cache store offline'
console.log(cause);
const full = await startup([errors(), cache]);
const text = isNexusError(full) ? full.message : null; // -> '[NEXUS_PLUGIN_FAILED] the setup hook of acme:cache failed: Error: cache store offline'
console.log(text);Try it: save the region as error.ts and run npx tsx error.ts. It prints four lines: the one-line message, then setup, the hook field, then Error: cache store offline, the cause as a string, then the full text, [NEXUS_PLUGIN_FAILED] the setup hook of acme:cache failed: Error: cache store offline, with no fix line. Then save the fix region below as fixed.ts and run npx tsx fixed.ts. It prints 1.21 true: the reactor output, then the flag that setup set.
Fix NEXUS_PLUGIN_FAILED
NEXUS_PLUGIN_FAILED is fixed in the plugin: read cause, which holds the error the hook threw, and correct what it names. For a third-party plugin, report the error to its authors with the plugin name and the hook. 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;
}
// The cache store answers now, so setup finishes.
let online = false;
const cache: NexusPlugin = {
name: 'acme:cache',
apiVersion: NEXUS_PLUGIN_API,
setup() {
online = true;
},
};
await using ship = await Nexus.create(
[provide(REACTOR, { useClass: FusionReactor })],
{ plugins: [cache] },
);
const output = ship.get(REACTOR).output; // -> 1.21
console.log(output, online);Try it: in fixed.ts, add the line throw new Error('cache store offline'); after online = true; in setup and run it again. tsc accepts the file. tsx throws an uncaught PluginError that starts with [NEXUS_PLUGIN_FAILED] plugin=acme:cache hook=setup. Delete the line and the program prints 1.21 true 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 asplugins[0]when it has no name or is not an object. It ispluginswhen the option is not an array.nullforNEXUS_PLUGIN_CONFLICT.reason: forNEXUS_PLUGIN_INVALID:not-an-array,not-an-object,no-name,duplicate-name,bad-hook,bad-compile,bad-modulesorbad-on-init.nullfor the other codes.detail: forNEXUS_PLUGIN_INVALID: an array of strings that names the value (not-an-array,not-an-objectandbad-on-init) or the hook key (bad-hook). Empty for every other reason and code.apiVersion: forNEXUS_PLUGIN_VERSION: the version the plugin declares, as a string such as'2', or'undefined'when it declares none.supported: forNEXUS_PLUGIN_VERSION: the plugin API versions this core supports, as an array of numbers. It holds[1]in 0.4.plugins: forNEXUS_PLUGIN_CONFLICT: the names of the first plugin that rewrote the definition and the later one that rewrote it again.target: forNEXUS_PLUGIN_CONFLICT: the name of the module or provider both rewrite.hook: forNEXUS_PLUGIN_FAILED: the hook that failed, one ofsetup,tokenKey,construct,compile.module,compile.providerandcompile.check.disposalErrors: forNEXUS_PLUGIN_FAILED: the errors thrown while disposing whatcreatehad built, as an array. It is empty unless asetupfailure closed the container.