payloadcms/payload · critical · Error

Task slug "${task.slug}" is already used by a workflow. No t

Error message

Task slug "${task.slug}" is already used by a workflow. No tasks are allowed to have the same slug as a workflow.

What it means

Thrown while building the jobs queue config collection when a task's slug collides with an existing workflow slug. Payload disallows the collision because task and workflow slugs share the same namespace on the jobs collection (taskSlugs seeds with 'inline'), so a duplicate would make job routing ambiguous.

Source

Thrown at packages/payload/src/queues/config/collection.ts:27

export const jobsCollectionSlug = 'payload-jobs'

export const getDefaultJobsCollection: (jobsConfig: SanitizedConfig['jobs']) => CollectionConfig = (
  jobsConfig,
) => {
  const workflowSlugs: Set<string> = new Set()
  const taskSlugs: Set<string> = new Set(['inline'])

  if (jobsConfig.workflows?.length) {
    jobsConfig.workflows.forEach((workflow) => {
      workflowSlugs.add(workflow.slug)
    })
  }

  if (jobsConfig.tasks?.length) {
    jobsConfig.tasks.forEach((task) => {
      if (workflowSlugs.has(task.slug)) {
        throw new Error(
          `Task slug "${task.slug}" is already used by a workflow. No tasks are allowed to have the same slug as a workflow.`,
        )
      }

      taskSlugs.add(task.slug)
    })
  }

  const logFields: Field[] = [
    {
      name: 'executedAt',
      type: 'date',
      required: true,
    },
    {
      name: 'completedAt',
      type: 'date',
      required: true,

View on GitHub (pinned to 00c58b35c0)

Solutions

  1. Rename the task slug so it is unique across both tasks and workflows.
  2. Audit `payload.config.ts` jobs.workflows and jobs.tasks for duplicate slugs before starting the server.
  3. Add a unit test that builds the config and asserts no slug overlap.

Example fix

// before
jobs: {
  workflows: [{ slug: 'sync', tasks: [] }],
  tasks: [{ slug: 'sync', handler: async () => {} }],
}

// after
jobs: {
  workflows: [{ slug: 'sync', tasks: [] }],
  tasks: [{ slug: 'sync-task', handler: async () => {} }],
}
Defensive patterns

Strategy: validation

Validate before calling

import config from './payload.config'

function assertNoSlugCollision(cfg): void {
  const workflows = new Set((cfg.jobs?.workflows ?? []).map((w) => w.slug))
  for (const t of cfg.jobs?.tasks ?? []) {
    if (workflows.has(t.slug)) {
      throw new Error(`Task slug "${t.slug}" collides with a workflow slug`)
    }
  }
}

assertNoSlugCollision(config)

Type guard

function isUniqueAcross<T extends { slug: string }>(
  a: T[],
  b: T[],
): boolean {
  const set = new Set(a.map((x) => x.slug))
  return b.every((x) => !set.has(x.slug))
}

if (!isUniqueCross(tasks, workflows)) {
  throw new Error('task/workflow slug collision')
}

Prevention

When it happens

Trigger: Defining `jobs.tasks` and `jobs.workflows` in buildConfig where a task and a workflow share the same `slug`. The error fires at config build time, before the server starts.

Common situations: Refactoring a workflow into a standalone task and forgetting to rename; copy-paste of a workflow config into tasks; renaming a workflow but leaving an old task with the same name.

Related errors


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