payloadcms / payloadcms/payload

payload migrate:create fails with ERR_MODULE_NOT_FOUND on TS imports without explicit extensions (Next 16 + ESM strict)

Open
#16,684 0 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

stale
Dominant language
TypeScript
Stars
44.8k
Forks
4.2k
Avg merge
2d 21h
Merged PRs (30d)
53

Description

Bug

npx payload migrate:create <name> (and any other payload CLI subcommand
that loads payload.config.ts) fails with ERR_MODULE_NOT_FOUND when
TypeScript imports in the config or in any collection file omit the
explicit file extension — which is the standard Next.js / Turbopack style.

The CLI uses a nested tsx (payload/node_modules/tsx) in strict ESM
mode that does not auto-resolve .ts extensions on relative imports.

Environment

  • payload@3.84.1
  • next@16.2.6
  • @payloadcms/db-postgres@3.84.1
  • Node 22.x, macOS 15

Repro

Project layout:

src/payload.config.ts
src/collections/Users.ts
src/collections/Articoli.ts

src/payload.config.ts:

import { Users } from './collections/Users'
import { Articoli } from './collections/Articoli'
// ...

Run:

npx payload migrate:create initial

Crash:

Error [ERR_MODULE_NOT_FOUND]: Cannot find module '/.../src/collections/Users' imported from /.../src/payload.config.ts
    at finalizeResolution (node:internal/modules/esm/resolve:275:11)
    at moduleResolve (node:internal/modules/esm/resolve:861:10)
    at resolve (.../payload/node_modules/tsx/dist/esm/index.mjs:2:5279)

The same imports work fine under next dev, next build, next start,
and standalone tsx (project-level dependency, not the nested one in
payload). The crash happens for payload --help, migrate:create,
migrate:status, generate:types — i.e. anything that loads the config.

Workaround

Add explicit .ts (or .js) extensions to every relative import in
payload.config.ts and in every file it transitively loads
(collections/*.ts, etc.). Invasive for an existing codebase.

Proposed fix

The Payload CLI should either:

  • use the same resolver semantics as Next.js / Turbopack
    (allow extensionless relative TS imports), or
  • document explicitly that the CLI requires .ts/.js extensions on
    relative imports, and validate payload.config.ts at startup with a
    clear error message instead of an opaque ERR_MODULE_NOT_FOUND.

The current behaviour silently breaks every Payload CLI subcommand on
any Next 16 project that follows the Next-recommended import style.

Workaround in use here

pg_dump --schema-only of the dev DB committed in scripts/, applied
manually on first deploy. Schema deltas tracked as raw .sql files
until the CLI is usable.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by tracing the Payload CLI entry points for payload --help, migrate:create, migrate:status, and generate:types to the loader for payload.config.ts, then inspect how the nested payload/node_modules/tsx resolver handles the imports shown in the report. Done means extensionless TypeScript imports work for config loading, or startup provides a clear documented validation error instead of ERR_MODULE_NOT_FOUND.

Written by the indexing model from the issue text.

Assessment

Tech stack
nextjs, node.js, typescript
Domain
cli
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.