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

  1. Route plugins through the manager/registry lifecycle so initialize(context) runs before any method call
  2. Move context-dependent logic (config reads, logging) out of constructors and field initializers into onInitialize()
  3. 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

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


AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18). Data as JSON: /api/errors/b16a169f1a484141. Report an issue: GitHub.