payloadcms/payload · critical · Error
Error: the payload config is required to initialize payload.
Error message
Error: the payload config is required to initialize payload.
What it means
Thrown during Payload initialization (the `Payload` class constructor/init) when `options.config` is falsy. Payload cannot build its logger, secret, or any subsystem without the resolved config object, so it refuses to boot. It is the first guard before `await options.config` is dereferenced.
Source
Thrown at packages/payload/src/index.ts:916
/**
* @description Initializes Payload
* @param options
*/
async init(options: InitOptions): Promise<Payload> {
if (
process.env.NODE_ENV !== 'production' &&
process.env.PAYLOAD_DISABLE_DEPENDENCY_CHECKER !== 'true' &&
!checkedDependencies
) {
checkedDependencies = true
void checkPayloadDependencies()
}
this.importMap = options.importMap!
if (!options?.config) {
throw new Error('Error: the payload config is required to initialize payload.')
}
this.config = await options.config
this.logger = getLogger('payload', this.config.logger)
if (!this.config.secret) {
throw new Error('Error: missing secret key. A secret key is needed to secure Payload.')
}
this.encryptionKeyring = buildEncryptionKeyring([
this.config.secret,
...(this.config.previousSecrets ?? []),
])
this.secret = this.encryptionKeyring.active.legacyKey
this.globals = {
config: this.config.globals,
}View on GitHub (pinned to 00c58b35c0)
Solutions
- Pass the resolved config: `payload.init({ config, secret })` or `new Payload().init({ config })`.
- Check that the config import is not undefined: log `typeof config` right before init to catch bad module resolution.
- If using Next.js, ensure `payload.config.ts` is the file actually imported (correct path/extension) and not shadowed.
Example fix
// before
payload.init({ secret })
// after
import config from './payload.config'
payload.init({ config, secret }) Defensive patterns
Strategy: validation
Validate before calling
import config from './payload.config'
if (!config) {
throw new Error('payload.config import resolved to undefined; check module resolution')
}
await payload.init({ config, secret: process.env.PAYLOAD_SECRET }) Type guard
import type { Config } from 'payload'
function isConfig(value: unknown): value is Config {
return Boolean(value && typeof value === 'object' && 'collections' in (value as object))
}
if (!isConfig(config)) throw new Error('Invalid payload config') Try / catch
try {
await payload.init({ config, secret })
} catch (err) {
if (err instanceof Error && err.message.includes('payload config is required')) {
// fix the config import / pass config, then retry startup
}
throw err
} Prevention
- Add a startup smoke test that builds the config and asserts it is non-undefined.
- Use a single canonical entry that imports config once and forwards it to init.
- After bundler/Next.js upgrades, verify the config module still resolves at runtime.
When it happens
Trigger: Constructing Payload and calling init() (or the internal init flow) without passing a `config` option, e.g. `payload.init({ secret, ... })` with no config, or passing config as undefined due to a bad import.
Common situations: A circular import or ESM/CJS resolution issue makes the config module evaluate to undefined; migrating to a bundler (Next.js, Turbopack) that tree-shakes the config import; misconfiguring the entry point so init runs before the config is loaded.
Related errors
- Error: missing secret key. A secret key is needed to secure
- Error: the payload config is required for getPayload to work
- Task slug "${task.slug}" is already used by a workflow. No t
- Error initializing MCP handler: ${String(error)}
- beginTransaction called while no connection to the database
AI-assisted analysis of payloadcms/payload@00c58b35c0 (2026-08-12).
Data as JSON: /api/errors/78381cf21376af3c.
Report an issue: GitHub.