payloadcms/payload · error · Error

Task ${taskSlug} not found in workflow ${job.workflowSlug}

Error message

Task ${taskSlug} not found in workflow ${job.workflowSlug}

What it means

Thrown inside `getRunTaskFunction` when a non-inline task slug referenced by the job does not exist in the workflow's `jobConfig.tasks` list. The runner looks up the task config by slug to find its handler and retries config; a miss means the job's stored task reference is out of sync with the deployed workflow config.

Source

Thrown at packages/payload/src/queues/operations/runJobs/runJob/getRunTaskFunction.ts:66

  ) =>
    (async (
      taskID: Parameters<RunInlineTaskFunction>[0],
      {
        input,
        retries,
        // Only available for inline tasks:
        task,
      }: Parameters<RunInlineTaskFunction>[1] & Parameters<RunTaskFunction<string>>[1],
    ) => {
      const executedAt = getCurrentDate()

      let taskConfig: TaskConfig | undefined
      if (!isInline) {
        taskConfig = (jobConfig.tasks?.length &&
          jobConfig.tasks.find((t) => t.slug === taskSlug)) as TaskConfig<string>

        if (!taskConfig) {
          throw new Error(`Task ${taskSlug} not found in workflow ${job.workflowSlug}`)
        }
      }

      const retriesConfigFromPropsNormalized =
        retries == undefined || retries == null
          ? {}
          : typeof retries === 'number'
            ? { attempts: retries }
            : retries
      const retriesConfigFromTaskConfigNormalized = taskConfig
        ? typeof taskConfig.retries === 'number'
          ? { attempts: taskConfig.retries }
          : taskConfig.retries
        : {}

      const finalRetriesConfig: RetryConfig = {
        ...retriesConfigFromTaskConfigNormalized,
        ...retriesConfigFromPropsNormalized, // Retry config from props takes precedence

View on GitHub (pinned to 00c58b35c0)

Solutions

  1. Ensure the workflow's `tasks` array defines a task with the exact slug the job references.
  2. Drain or migrate queued jobs before deploying a workflow that renames/removes a task.
  3. Inspect the failing job document's `workflowSlug`/task reference and reconcile with current config.

Example fix

// before
workflows: [{
  slug: 'import',
  tasks: [{ slug: 'parse' /* but job references 'parse-csv' */ }],
}]

// after
workflows: [{
  slug: 'import',
  tasks: [{ slug: 'parse-csv', handler: async () => {} }],
}]
Defensive patterns

Strategy: try-catch

Validate before calling

import type { Config } from 'payload'

function assertWorkflowTaskExists(cfg: Config, workflowSlug: string, taskSlug: string): void {
  const wf = cfg.jobs?.workflows?.find((w) => w.slug === workflowSlug)
  const exists = wf?.tasks?.some((t) => t.slug === taskSlug)
  if (!exists) {
    throw new Error(`Task ${taskSlug} not defined in workflow ${workflowSlug}`)
  }
}

Type guard

function workflowDefinesTask(
  workflows: { slug: string; tasks?: { slug: string }[] }[],
  workflowSlug: string,
  taskSlug: string,
): boolean {
  return workflows
    .find((w) => w.slug === workflowSlug)
    ?.tasks?.some((t) => t.slug === taskSlug) ?? false
}

Try / catch

try {
  await runJobs({ req })
} catch (err) {
  if (err instanceof Error && err.message.includes('not found in workflow')) {
    // reconcile job data with current workflow config; drain stale jobs
  } else throw err
}

Prevention

When it happens

Trigger: A queued job references a task slug that was renamed or removed from the workflow after the job was enqueued; running old job data against a newer workflow config; a typo in the task slug used in a workflow's `tasks` wiring.

Common situations: Deploying a workflow change (rename/remove task) while jobs referencing the old task are still in the queue; branching config divergence; manually inserted job rows with wrong task slugs.

Related errors


AI-assisted analysis of payloadcms/payload@00c58b35c0 (2026-08-12). Data as JSON: /api/errors/68ca2ed5c9ff2184. Report an issue: GitHub.