immich-app/immich · error

Plugin method call failed

Error message

Plugin method call failed: ${label}#${methodName}

What it means

callMethod acquires a worker from the plugin pool, calls the requested method, and wraps any failure (plugin throws, worker crashes, serialization error, timeout) in 'Plugin method call failed: <label>#<methodName>' with the cause preserved. The plugin itself remains loaded; only the method invocation failed.

Solutions

  1. Inspect the `cause` for the actual error thrown inside the plugin method
  2. Validate/serialize the input payload before the call (ensure JSON.stringify works and shape matches the method contract)
  3. Check worker logs/health for crashes (OOM, unhandled rejection) at the time of the call
  4. Reproduce the method call with the same input directly against the plugin to debug

Example fix

// before
const r = await pluginRepo.callMethod({ pluginKey: 'geo-plugin', methodName: 'geocode' }, circularObj);
// after
const r = await pluginRepo.callMethod({ pluginKey: 'geo-plugin', methodName: 'geocode' }, JSON.parse(JSON.stringify(sanitizedInput)));
Defensive patterns

Strategy: try-catch

Validate before calling

// guard input serializability and shape before calling
const payload = JSON.parse(JSON.stringify(input)); // throws on circular refs early
assertSchema(methodName, payload); // validate against the plugin's method contract

Try / catch

try {
  return await pluginRepo.callMethod({ pluginKey, methodName }, input, context);
} catch (e) {
  if (String(e.message).startsWith('Plugin method call failed')) {
    logger.error(`${(e as any).cause?.message ?? e}`); // real error from the plugin
    throw new PluginInvocationError(pluginKey, methodName, e);
  }
  throw e;
}

Prevention

When it happens

Trigger: pool.acquire() or plugin.call(methodName, JSON.stringify(input), context) rejects — the plugin method threw, input was not JSON-serializable, the worker crashed mid-call, or the call timed out.

Common situations: Plugin method received unexpected input shape and threw internally; NaN/circular objects failing JSON.stringify; worker OOM or crash under load; bug in a newly deployed plugin version.

Understand the failure class

Background: "API request failed": what wrapped HTTP errors from external APIs mean and how to find the real cause — this error's family across 29 libraries.

Related errors


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

Appendix: source

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

  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)