ruvnet/ruflo · critical
Plugin initialization failed: ${initErrors.join(' ')}
Error message
Plugin initialization failed:
${initErrors.join('
')} What it means
Thrown at the end of EnhancedPluginRegistry.initialize() when any plugin's init recorded an error. Initialization runs by strategy (sequential, parallel, parallel-safe) and captures per-plugin failures into each entry's error field instead of throwing immediately; afterwards initialize() collects every 'pluginName: error' pair and throws this aggregate, so one or more plugin init failures abort the whole registry initialization (initialized stays false).
Source
Thrown at v3/@claude-flow/plugins/src/registry/enhanced-plugin-registry.ts:423
switch (strategy) {
case 'sequential':
await this.initializeSequential();
break;
case 'parallel':
await this.initializeParallel();
break;
case 'parallel-safe':
await this.initializeParallelSafe();
break;
}
// Check for initialization errors (including conflicts)
const initErrors = Array.from(this.plugins.values())
.filter(e => e.error)
.map(e => `${e.plugin.metadata.name}: ${e.error}`);
if (initErrors.length > 0) {
throw new Error(`Plugin initialization failed:\n${initErrors.join('\n')}`);
}
this.initialized = true;
this.logger.info(`Registry initialized with ${this.plugins.size} plugins (${strategy})`);
}
private async initializeSequential(): Promise<void> {
const loadOrder = this.dependencyGraph.getLoadOrder();
for (const name of loadOrder) {
const entry = this.plugins.get(name);
if (!entry) continue;
if (!entry.config.enabled) {
this.logger.info(`Plugin ${name} is disabled, skipping initialization`);
continue;
}
View on GitHub (pinned to fa13ee4ad6)
Solutions
- Parse each line of the aggregate message to find which plugin(s) failed and why; fix that plugin's init problem (config, credentials, connectivity)
- Make the failing plugin's init resilient (retry, defaults, or graceful degradation) so a single plugin cannot abort registry startup
- For name-collision errors, change the registry's conflict resolution strategy away from 'error' or rename the conflicting extension
- If the plugin is non-essential, unregister it (or register it later) so initialize() can succeed without it
Example fix
// before
await registry.initialize();
// throws: Plugin initialization failed:
// db-plugin: connect ECONNREFUSED localhost:5432
// after - make the plugin's init non-fatal:
async init(ctx) {
try {
await this.client.connect();
} catch (err) {
ctx.logger.warn('db-plugin degraded:', err.message);
this.degraded = true; // init() still resolves
}
}
await registry.initialize(); // succeeds, db-plugin degraded Defensive patterns
Strategy: try-catch
Validate before calling
// Optional dry run: surface failing init early per-plugin instead of aborting the registry
for (const plugin of pluginsToLoad) {
try {
await plugin.init?.({ logger }); // minimal context
} catch (err) {
logger.warn(`plugin ${plugin.metadata.name} init will fail: ${(err as Error).message}`);
}
} Try / catch
try {
await registry.initialize();
} catch (err) {
if (err instanceof Error && err.message.startsWith('Plugin initialization failed')) {
const failed = err.message.split('\n').slice(1); // 'name: cause' lines
for (const line of failed) logger.error(`init failure: ${line}`);
// option: unregister failing plugins and retry initialize() on a fresh registry
}
throw err;
} Prevention
- Make non-essential plugin init non-fatal: degrade inside init() instead of rejecting
- Validate plugin config (env vars, credentials, endpoints) before initialize() runs
- Prefer the 'parallel-safe' strategy so one plugin's init failure does not poison others
- Surface per-plugin init health in diagnostics after boot
When it happens
Trigger: A plugin's init() rejecting (bad config, missing API key, unreachable service) during initialize(); initialization conflicts recorded as errors (e.g. extension name collisions under the 'error' resolution strategy); a plugin timing out within its init and recording an error; any strategy (sequential/parallel/parallel-safe) since all funnel through the same post-check.
Common situations: External-service plugins (DB, LLM) whose init fails from missing env vars/credentials in the deployed environment; order-dependent plugins initializing in parallel and conflicting; one broken third-party plugin blocking the entire app boot; transient network failure during init treated as fatal.
Related errors
- Invalid plugin: does not implement IPlugin interface
- Plugin ${name} already registered
- Maximum plugin limit (${this.config.maxPlugins}) reached
- Plugin ${name} requires core version >= ${resolvedPlugin.met
- Plugin ${name} requires core version <= ${resolvedPlugin.met
AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18).
Data as JSON: /api/errors/8df03bbe9d3147f8.
Report an issue: GitHub.