immich-app/immich · error

No loaded plugin found for

Error message

No loaded plugin found for ${pluginKey}

What it means

callMethod looks up the plugin by pluginKey in the repository's pluginMap; if no plugin with that key was ever loaded (or it failed to load and was never registered), it throws 'No loaded plugin found for <pluginKey>'. This is a lookup/lifecycle error — the method call cannot proceed.

Solutions

  1. Confirm load() succeeded for that pluginKey before calling callMethod (check startup logs)
  2. Verify the exact pluginKey string matches the one passed to load()
  3. Add an existence check or registry query before invoking callMethod
  4. Fix startup ordering so dependent services wait for plugin loading to complete

Example fix

// before
await pluginRepo.callMethod({ pluginKey: 'geo-plugin', methodName: 'geocode' });
// after
await pluginRepo.load({ key: 'geo-plugin', label: 'Geo' /* ... */ });
await pluginRepo.callMethod({ pluginKey: 'geo-plugin', methodName: 'geocode' });
Defensive patterns

Strategy: validation

Validate before calling

// assume repo exposes loaded keys or track them yourself
if (!loadedPluginKeys.has(pluginKey)) {
  throw new Error(`Plugin '${pluginKey}' not loaded — call load() first`);
}

Try / catch

try {
  return await pluginRepo.callMethod({ pluginKey, methodName }, input);
} catch (e) {
  if (String(e.message).startsWith('No loaded plugin found')) {
    logger.error(`Plugin ${pluginKey} unavailable (not loaded or failed to load)`);
    return fallbackResult(methodName, input);
  }
  throw e;
}

Prevention

When it happens

Trigger: callMethod({pluginKey, methodName}) is invoked with a pluginKey that is absent from pluginMap — typo in key, plugin load failed earlier, plugin not loaded yet (race before load completes), or plugin was unloaded.

Common situations: Key renamed in code but callers still use the old name; startup ordering issue where a feature calls the plugin before load() finishes; earlier 'Unable to instantiate plugin' left the plugin unregistered; environment where the plugin is intentionally not deployed.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


AI-assisted analysis of immich-app/immich@e55ac299a4 (2026-09-15). Data as JSON: /api/errors/a5f23b0fd4c21f9d. Report an issue: GitHub.

Appendix: source

Thrown at server/src/repositories/plugin.repository.ts:247

            },
          ),
        destroy: (plugin) => plugin.close(),
      },
      { min: 1, max: 5 },
    );

    try {
      await pool.ready();
      this.pluginMap.set(key, { pool, label });
    } catch (error: Error | any) {
      throw new Error(`Unable to instantiate plugin: ${key}`, { cause: error });
    }
  }

  async callMethod<T>({ pluginKey, methodName }: PluginMethod, input: unknown, context?: unknown) {
    const item = this.pluginMap.get(pluginKey);
    if (!item) {
      throw new Error(`No loaded plugin found for ${pluginKey}`);
    }

    const { pool, label } = item;

    try {
      const plugin = await pool.acquire();
      try {
        const result = await plugin.call(methodName, JSON.stringify(input), context);
        return (result ? result.json() : result) as T;
      } finally {
        await pool.release(plugin);
      }
    } catch (error: Error | any) {
      throw new Error(`Plugin method call failed: ${label}#${methodName}`, { cause: error });
    }
  }
}

View on GitHub (pinned to e55ac299a4)