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

  1. Pass the resolved config: `payload.init({ config, secret })` or `new Payload().init({ config })`.
  2. Check that the config import is not undefined: log `typeof config` right before init to catch bad module resolution.
  3. 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

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


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