payloadcms / payloadcms/payload
bin/loadEnv.js: default import on @next/env breaks under tsx CJS transpile
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 44.8k
- Forks
- 4.2k
- Avg merge
- 2d 21h
- Merged PRs (30d)
- 53
Description
Bug
payload/dist/bin/loadEnv.js uses a default import on @next/env:
import nextEnvImport from '@next/env';
const { loadEnvConfig } = nextEnvImport;
@next/env is a webpack-bundled namespace module that exports only named
exports (loadEnvConfig, initialEnv, processEnv, resetEnv,
updateInitialEnv) with __esModule: true and no default property.
When this file is transpiled to CJS by tsx/esbuild (e.g. when running a
TypeScript script that imports getPayload and @payloadcms/drizzle
transitively pulls in payload/node), esbuild's __toESM helper sees the
__esModule: true marker and does not synthesize a default export.
Result: nextEnvImport is undefined, the destructure throws at module
load time, the entire chain crashes before any user code runs.
Repro
- Project on
next@16+payload@3.84.1+@payloadcms/db-postgres. - A TS script
seed.ts:
import { getPayload } from 'payload'
import config from './payload.config'
await getPayload({ config })
- Run:
node --env-file=.env.local node_modules/tsx/dist/cli.mjs seed.ts
Crash:
TypeError: Cannot destructure property 'loadEnvConfig' of 'import_env.default' as it is undefined.
at .../payload/dist/bin/loadEnv.js:3:9
at Object.<anonymous> (.../payload/dist/bin/loadEnv.js:6:21)
at Module._compile (node:internal/modules/cjs/loader:1705:14)
at Object.transformer (.../tsx/dist/register-DJgoUG_Q.cjs:9:1709)
Fix
Use a namespace import. The destructure target becomes the namespace
object (which exposes the named exports directly) and the interop bug
disappears in both CJS and ESM:
import * as nextEnv from '@next/env';
const { loadEnvConfig } = nextEnv;
One file, two lines. Diff:
diff --git a/node_modules/payload/dist/bin/loadEnv.js b/node_modules/payload/dist/bin/loadEnv.js
index b61ecc1..58eaeda 100644
--- a/node_modules/payload/dist/bin/loadEnv.js
+++ b/node_modules/payload/dist/bin/loadEnv.js
@@ -1,6 +1,6 @@
-import nextEnvImport from '@next/env';
+import * as nextEnv from '@next/env';
import { findUpSync } from '../utilities/findUp.js';
-const { loadEnvConfig } = nextEnvImport;
+const { loadEnvConfig } = nextEnv;
/**
* Try to find user's env files and load it. Uses the same algorithm next.js uses to parse env files, meaning this also supports .env.local, .env.development, .env.production, etc.
*/ export function loadEnv(path) {
(The source .ts file mirrors the same change: replace
import nextEnvImport from '@next/env' with
import * as nextEnv from '@next/env' and update the destructure.)
Workaround (until released)
patch-package with the diff above, applied via postinstall.
Environment
payload@3.84.1next@16.2.6(pulls@next/env@16.2.6)payloadbundles@next/env@15.5.18— bug present in both versionstsx@4.19.x- Node 22.x
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 with bin/loadEnv.js and locate the corresponding source .ts file that imports @next/env. Reproduce the failure with the provided tsx command and verify the import and destructuring change against both CJS and ESM usage. Done means the seed.ts example loads without the module-load TypeError.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- next.js, node.js, typescript
- Domain
- backend, tooling
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 74/100