INJECUTE_ALREADY_REGISTERED
The key is already registered in this container or a parent.
How to fix it
Pass { replace: true } to replace the registration, or use another key. In a fork, { replace: true } is needed to override a parent's key too, and the override reaches only services resolved in the fork: services registered in the parent keep the parent's one. To replace it for every service, use fork({ isolated: true }).
Example
app.addInstance('logger', console).addInstance('logger', pino()); // throws
app.addInstance('logger', pino(), { replace: true }); // replaces it
app.fork().addInstance('logger', pino()); // throws: the parent has "logger"
app.fork().addInstance('logger', pino(), { replace: true }); // overrides it in the forkOverriding a parent's key in a fork
A fork needs { replace: true } to register a key its parent has, because the override doesn't reach everything. In a plain fork it reaches only the services resolved in the fork: a service registered in the parent runs and is cached in the parent, so it keeps the parent's instance. The error names those services:
const app = new DIContainer()
.addSingleton('tx', (db) => db.begin(), ['db'])
.addSingleton('report', Report, ['tx']);
app.fork().addSingleton('tx', (db) => db.begin(), ['db']);
// throws: "report" (registered in a parent) depends on "tx" and keeps the parent's "tx"What to do depends on what you want:
- Only the fork's own services should use the new one: pass
{ replace: true }. - A parent service should use it too: register that service in the fork as well (for a scope's services, in a scope module), and don't register the key in the root.
- Every service should use it (tests, a variant of the app): use an isolated fork, with
{ replace: true }.
To wrap the existing service instead of replacing it, depend on its own key (see Decorating a service).
Handling it in code
import { InjecuteError } from 'injecute';
try {
// ...
} catch (error) {
if (error instanceof InjecuteError && error.code === 'INJECUTE_ALREADY_REGISTERED') {
// error.message explains what happened; error.path is the resolution chain
}
}