payloadcms/payload · error · Error

Error importing job queue handler module for path ${path}. T

Error message

Error importing job queue handler module for path ${path}. This is an advanced feature that may require a sophisticated build pipeline, especially when using it in production or within Next.js, e.g. by calling opening the /api/payload-jobs/run endpoint. You will have to transpile the handler files separately and ensure they are available in the same location when the job is run. If you're using an endpoint to execute your jobs, it's recommended to define your handlers as functions directly in your Payload Config, or use import paths handlers outside of Next.js. Import Error: 
${e instanceof Error ? e.message : 'Unknown error'}

What it means

Thrown by `importHandlerPath` when the dynamic import of a task/workflow handler module (referenced by `handler.path`, split on `#` for named export) fails. The path-based handler is an advanced feature: the module must be importable at runtime, which bundlers (especially Next.js production builds) often break by not emitting/transpiling those files. The message includes the underlying import error for diagnosis.

Source

Thrown at packages/payload/src/queues/operations/runJobs/runJob/importHandlerPath.ts:16

import type { TaskConfig, TaskHandler, TaskSlug } from '../../../config/types/taskTypes.js'

import { dynamicImport } from '../../../../utilities/dynamicImport.js'

/**
 * Imports a handler function from a given path.
 */
export async function importHandlerPath<T>(path: string): Promise<T> {
  let runner!: T
  const [runnerPath, runnerImportName] = path.split('#')

  let runnerModule: Record<string, unknown>
  try {
    runnerModule = await dynamicImport<Record<string, unknown>>(runnerPath!)
  } catch (e) {
    throw new Error(
      `Error importing job queue handler module for path ${path}. This is an advanced feature that may require a sophisticated build pipeline, especially when using it in production or within Next.js, e.g. by calling opening the /api/payload-jobs/run endpoint. You will have to transpile the handler files separately and ensure they are available in the same location when the job is run. If you're using an endpoint to execute your jobs, it's recommended to define your handlers as functions directly in your Payload Config, or use import paths handlers outside of Next.js. Import Error: \n${e instanceof Error ? e.message : 'Unknown error'}`,
    )
  }

  // If the path has indicated an #exportName, try to get it
  if (runnerImportName && runnerModule[runnerImportName]) {
    runner = runnerModule[runnerImportName] as T
  }

  // If there is a default export, use it
  if (!runner && runnerModule.default) {
    runner = runnerModule.default as T
  }

  // Finally, use whatever was imported
  if (!runner) {
    runner = runnerModule as T
  }

View on GitHub (pinned to 00c58b35c0)

Solutions

  1. Prefer defining handlers as functions directly in the Payload config instead of `handler.path`.
  2. If you must use a path, transpile/emit the handler file separately and confirm it exists in the build output.
  3. Run the import path outside Next.js (e.g. a standalone worker) where the file is on disk.

Example fix

// before
handler: { path: './tasks/sync.js#run' }

// after
import { run as syncRun } from './tasks/sync.js'
handler: syncRun
Defensive patterns

Strategy: fallback

Validate before calling

// prefer function handlers in config so dynamic import is unnecessary
import { run as syncRun } from './tasks/sync.js'

tasks: [{ slug: 'sync', handler: syncRun }]

Type guard

function isHandlerFunction(value: unknown): value is (...args: any[]) => any {
  return typeof value === 'function'
}

if (!isHandlerFunction(handler)) {
  throw new Error('handler.path is not recommended in bundled builds; use a function handler')
}

Try / catch

try {
  await runJobs({ req })
} catch (err) {
  if (err instanceof Error && err.message.includes('Error importing job queue handler module')) {
    // switch the task to a function handler, or ensure the module is emitted in the build
  } else throw err
}

Prevention

When it happens

Trigger: A task/workflow uses `handler: { path: './tasks/foo.js#run' }` and the dynamic import of `./tasks/foo.js` throws — file missing in the build output, wrong extension, ESM/CJS mismatch, or the module is outside the bundle.

Common situations: Deploying to Next.js/Vercel where the handler file isn't included in the server bundle; moving handler files without updating paths; using a path that resolves in dev but not in a transpiled prod build.

Related errors


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