{"record":{"id":"5040c26639524894","repo":"immich-app/immich","slug":"method-step-method-is-incompatible-with-workf","errorCode":null,"errorMessage":"Method \"${step.method}\" is incompatible with workflow trigger: \"${trigger}\"","messagePattern":"Method \"(.+?)\" is incompatible with workflow trigger: \"(.+?)\"","errorType":"exception","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"server/src/services/workflow.service.ts","lineNumber":116,"sourceCode":"            index: entry.step.order,\n            method: `${entry.step.pluginId}#${entry.step.methodName}`,\n          }\n        : undefined,\n    }));\n  }\n\n  private async resolveAndValidateSteps<T extends { method: string }>(steps: T[], trigger: WorkflowTrigger) {\n    const methods = await this.pluginRepository.getForValidation();\n    const results: Array<T & { pluginMethod: PluginMethodSearchResponse }> = [];\n\n    for (const step of steps) {\n      const pluginMethod = resolveMethod(methods, step.method);\n      if (!pluginMethod) {\n        throw new BadRequestException(`Unknown method ${step.method}`);\n      }\n\n      if (!isMethodCompatible(pluginMethod, trigger)) {\n        throw new BadRequestException(`Method \"${step.method}\" is incompatible with workflow trigger: \"${trigger}\"`);\n      }\n\n      results.push({ ...step, pluginMethod });\n    }\n\n    // TODO make sure all steps can use a common WorkflowType\n\n    return results;\n  }\n\n  private findOrFail(id: string) {\n    return findOrFail(() => this.workflowRepository.get(id), 'Workflow');\n  }\n}\n","sourceCodeStart":98,"sourceCodeEnd":131,"githubUrl":"https://github.com/immich-app/immich/blob/e55ac299a4ec7cb372e35dbf2c6c05ee9ce77f6c/server/src/services/workflow.service.ts#L98-L131","documentation":"resolveAndValidateSteps checks each resolved plugin method against the workflow's trigger via isMethodCompatible. When the method exists but does not support the workflow's trigger type (e.g. an asset-triggered workflow using a manual-only method), a 400 Bad Request naming both the method and trigger is thrown.","triggerScenarios":"Creating/updating a workflow where a step's method is valid but its supported trigger set does not include the workflow's trigger (e.g. method supports 'manual' but the workflow trigger is 'asset-upload').","commonSituations":"Reusing a step template across workflows with different triggers; plugin updates changing which triggers a method supports; building workflows in the API without consulting method-trigger compatibility metadata; client UI bug allowing incompatible steps to be submitted.","solutions":["Choose a method that supports the workflow's trigger — check the plugin method's compatible-triggers metadata.","Change the workflow's trigger type to one the existing steps support.","Remove or replace the incompatible step.","After a plugin update, re-validate existing workflows; rebuild steps whose trigger compatibility changed."],"exampleFix":"// before\n// trigger: manual, but method only supports asset events\n{ \"trigger\": \"manual\", \"steps\": [{ \"method\": \"asset.tagPeople\" }] }\n// after\n{ \"trigger\": \"asset-upload\", \"steps\": [{ \"method\": \"asset.tagPeople\" }] }","handlingStrategy":"validation","validationCode":"const methods = await api.getPluginMethods();\nconst compatible = (m: string, trigger: Trigger) => {\n  const pm = methods.find((x) => x.id === m);\n  return pm?.supportedTriggers.includes(trigger);\n};\nif (!steps.every((s) => compatible(s.method, trigger))) {\n  throw new Error('step method incompatible with workflow trigger');\n}","typeGuard":null,"tryCatchPattern":"try {\n  await api.createWorkflow({ trigger, steps });\n} catch (e) {\n  if (e instanceof BadRequestException && e.message.includes('is incompatible with workflow trigger')) {\n    // swap the step or change the workflow trigger\n  }\n}","preventionTips":["Check each method's supported-triggers metadata before adding it to a workflow.","Don't reuse step templates across workflows with different triggers.","After plugin updates, re-validate existing workflows.","Build workflows in the UI, which filters methods by trigger, rather than raw API calls."],"tags":["workflow","trigger","compatibility","validation"],"backgroundTag":"incompatible-source-type","analyzedSha":"e55ac299a4ec7cb372e35dbf2c6c05ee9ce77f6c","analyzedAt":"2026-09-15T07:20:19.675Z","contentChangedAt":"2026-09-15T07:20:19.675Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}