ruvnet/ruflo · error · Error
Plugin ${this.metadata.name} not initialized
Error message
Plugin ${this.metadata.name} not initialized What it means
BasePlugin's this.context, this.config, and this.logger all dereference this._context, which the plugin manager sets inside initialize(context). Any access before initialize() completes (or after dispose clears it) throws 'Plugin <name> not initialized'. Since initialize() assigns _context before invoking subclass hooks, the usual culprit is code running entirely outside the lifecycle: constructors, field initializers, or methods called manually.
Source
Thrown at v3/@claude-flow/plugins/src/core/base-plugin.ts:111
// =========================================================================
get state(): PluginLifecycleState {
return this._state;
}
protected setState(state: PluginLifecycleState): void {
const previousState = this._state;
this._state = state;
this.emit('stateChange', { previousState, currentState: state });
}
// =========================================================================
// Context Accessors
// =========================================================================
protected get context(): PluginContext {
if (!this._context) {
throw new Error(`Plugin ${this.metadata.name} not initialized`);
}
return this._context;
}
protected get config(): PluginConfig {
return this.context.config;
}
protected get logger(): ILogger {
return this.context.logger;
}
protected get eventBus(): IEventBus {
return this.context.eventBus;
}
protected get services(): ServiceContainer {
return this.context.services;View on GitHub (pinned to fa13ee4ad6)
Solutions
- Route plugins through the manager/registry lifecycle so initialize(context) runs before any method call
- Move context-dependent logic (config reads, logging) out of constructors and field initializers into onInitialize()
- If driving the lifecycle manually, call and await plugin.initialize(ctx) before invoking anything else on the instance
Example fix
// before
class MyPlugin extends BasePlugin {
private prefix = this.config.prefix; // throws: not initialized
}
// after
class MyPlugin extends BasePlugin {
private prefix?: string;
protected async onInitialize(): Promise<void> {
this.prefix = this.config.prefix; // context available here
}
} Defensive patterns
Strategy: validation
Validate before calling
// Always complete the lifecycle before touching plugin internals: const plugin = new MyPlugin(); await plugin.initialize(context); // sets _context // only now is it safe to call methods that use this.context/config/logger // never access context-dependent members in constructors or field initializers
Type guard
type Stateful = { state?: string };
/** Duck-typed readiness check if your plugin class exposes its lifecycle state. */
function isPluginReady(p: Stateful): boolean {
return p.state === 'initialized';
} Prevention
- Keep all config/logger usage inside onInitialize() and later lifecycle methods
- Do not call plugin helpers on manually instantiated plugins without initialize()
- Drop context usage after dispose/teardown — _context is cleared
When it happens
Trigger: A subclass reading this.config or this.logger in its constructor or in a class-field initializer; calling plugin methods directly on a manually instantiated plugin without registry.initialize(); wiring event handlers at construction time that touch this.context; using the plugin after dispose cleared the context.
Common situations: Manually new-ing a plugin class for testing and calling a helper without initialize; refactoring logic out of onInitialize() into the constructor; singleton plugins reused after teardown.
Related errors
- Plugin ${this.metadata.name} already initialized
- Connection pool not initialized
- RuVector Bridge not initialized. Call initialize() first.
- Can only resume paused agent
- SSRF guard: invalid URL — ${rawUrl}
AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18).
Data as JSON: /api/errors/b16a169f1a484141.
Report an issue: GitHub.