ruvnet/ruflo · error · Error

Collection ${collection.id} already loaded

Error message

Collection ${collection.id} already loaded

What it means

CollectionManager.loadCollection registers a collection by ID and refuses a second load of the same ID to prevent duplicate plugin registration. The check is against the collections map, so a collection must be unloaded before it can be loaded again in the same manager instance.

Source

Thrown at v3/@claude-flow/plugins/src/collections/collection-manager.ts:125

  private pluginSettings = new Map<string, Record<string, unknown>>();
  private registry: PluginRegistry;
  private autoInitialize: boolean;

  constructor(config: CollectionManagerConfig) {
    this.registry = config.registry;
    this.autoInitialize = config.autoInitialize ?? true;
  }

  // =========================================================================
  // Collection Management
  // =========================================================================

  /**
   * Load a plugin collection.
   */
  async loadCollection(collection: PluginCollection): Promise<void> {
    if (this.collections.has(collection.id)) {
      throw new Error(`Collection ${collection.id} already loaded`);
    }

    // Resolve all plugins upfront to cache names
    const resolved: ResolvedEntry[] = [];
    for (const entry of collection.plugins) {
      const plugin = await this.resolvePlugin(entry.plugin);
      resolved.push({
        entry,
        pluginName: plugin.metadata.name,
        plugin,
      });
    }

    this.collections.set(collection.id, collection);
    this.resolvedEntries.set(collection.id, resolved);
    this.enabledOverrides.set(collection.id, new Set());
    this.disabledOverrides.set(collection.id, new Set());

View on GitHub (pinned to fa13ee4ad6)

Solutions

  1. Call unloadCollection(id) and let it finish before loading the same ID again
  2. Track loaded collections and skip redundant loads
  3. Use a fresh CollectionManager per test or session instead of a shared singleton

Example fix

// before
await manager.loadCollection(collection); // second call throws 'already loaded'

// after
if (loadedIds.has(collection.id)) {
  await manager.unloadCollection(collection.id);
  loadedIds.delete(collection.id);
}
await manager.loadCollection(collection);
loadedIds.add(collection.id);
Defensive patterns

Strategy: validation

Validate before calling

const loadedIds = new Set<string>();
async function loadOnce(manager: CollectionManager, collection: PluginCollection) {
  if (loadedIds.has(collection.id)) return; // or unload first to reload
  await manager.loadCollection(collection);
  loadedIds.add(collection.id);
}

Try / catch

try {
  await manager.loadCollection(collection);
} catch (e) {
  if (e instanceof Error && e.message.endsWith('already loaded')) {
    await manager.unloadCollection(collection.id);
    await manager.loadCollection(collection); // reload
  } else throw e;
}

Prevention

When it happens

Trigger: Calling loadCollection twice with the same collection.id; hot-reload flows that load a new version before unloading the old one; reusing a single CollectionManager across tests without unloading.

Common situations: Test suites sharing manager state; watch-mode or reload loops; startup code that loads a collection while a plugin also loads it explicitly.

Related errors


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