immich-app/immich · error · BadRequestException

Unknown method ${step.method}

Error message

Unknown method ${step.method}

What it means

A BadRequestException (HTTP 400) thrown by WorkflowService.resolveAndValidateSteps when a workflow step's method string cannot be resolved to any loaded plugin method. The method string is parsed via the regex name[@version]#method and matched against pluginRepository.getForValidation(); no match yields this error.

Source

Thrown at server/src/services/workflow.service.ts:93

      })),
    );

    return mapWorkflow(workflow);
  }

  async delete(auth: AuthDto, id: string): Promise<void> {
    await this.requireAccess({ auth, permission: Permission.WorkflowDelete, ids: [id] });
    await this.workflowRepository.delete(id);
  }

  private async resolveAndValidateSteps<T extends { method: string }>(steps: T[], trigger: WorkflowTrigger) {
    const methods = await this.pluginRepository.getForValidation();
    const results: Array<T & { pluginMethod: PluginMethodSearchResponse }> = [];

    for (const step of steps) {
      const pluginMethod = resolveMethod(methods, step.method);
      if (!pluginMethod) {
        throw new BadRequestException(`Unknown method ${step.method}`);
      }

      if (!isMethodCompatible(pluginMethod, trigger)) {
        throw new BadRequestException(`Method "${step.method}" is incompatible with workflow trigger: "${trigger}"`);
      }

      results.push({ ...step, pluginMethod });
    }

    // TODO make sure all steps can use a common WorkflowType

    return results;
  }

  private findOrFail(id: string) {
    return findOrFail(() => this.workflowRepository.get(id), 'Workflow');
  }
}

View on GitHub (pinned to 199723261c)

Solutions

  1. Confirm the plugin is imported and enabled via GET /plugins and that the method is listed.
  2. Correct the method string to the exact 'pluginName[@version]#methodName' format returned by the plugin search endpoint.
  3. Re-import or update the plugin if the expected method is missing.
  4. Match the version segment if the plugin has multiple versions installed.

Example fix

// before
{ "method": "myplugin#doThin" } // typo in method name

// after
{ "method": "myplugin@1.2.0#doThing" } // exact name and version from /plugins
Defensive patterns

Strategy: validation

Validate before calling

async function methodExists(methodString) {
  const methods = await api.listPluginMethods();
  const parsed = parseMethodString(methodString); // name[@version]#method
  return methods.some((m) => m.pluginName === parsed?.pluginName && m.name === parsed?.methodName);
}
for (const step of dto.steps) {
  if (!(await methodExists(step.method))) {
    return badRequest(`Unknown method ${step.method}`);
  }
}

Type guard

const isUnknownMethodError = (e: unknown): boolean =>
  typeof e === 'object' && e !== null && (e as any).status === 400 &&
  typeof (e as any).message === 'string' && (e as any).message.startsWith('Unknown method');

Try / catch

try {
  await api.createWorkflow(dto);
} catch (e) {
  if (isUnknownMethodError(e)) {
    setFieldError('steps', e.message);
    return;
  }
  throw e;
}

Prevention

When it happens

Trigger: POST/PUT /workflows with a step.method like 'myplugin#doThing' where no enabled plugin named 'myplugin' exposing method 'doThing' is loaded. Also when the method string is malformed (missing '#' separator) so parseMethodString returns undefined.

Common situations: Plugin not yet imported or disabled; typo in plugin or method name; version mismatch (method exists in v2 but step references v1); plugin failed to import due to a WASM error; method string format changed.

Related errors


AI-assisted analysis of immich-app/immich@199723261c (2026-08-12). Data as JSON: /api/errors/7316a05bed696fb1. Report an issue: GitHub.