payloadcms / payloadcms/payload
payload migrate:create fails with ERR_MODULE_NOT_FOUND on TS imports without explicit extensions (Next 16 + ESM strict)
Nobody has claimed this yet.
- 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.1next@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/.jsextensions on
relative imports, and validatepayload.config.tsat startup with a
clear error message instead of an opaqueERR_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
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- 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