{"record":{"id":"7511f9cc121926f3","repo":"payloadcms/payload","slug":"error-missing-secret-key-a-secret-key-is-needed","errorCode":null,"errorMessage":"Error: missing secret key. A secret key is needed to secure Payload.","messagePattern":"Error: missing secret key\\. A secret key is needed to secure Payload\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"critical","filePath":"packages/payload/src/index.ts","lineNumber":923,"sourceCode":"      process.env.NODE_ENV !== 'production' &&\n      process.env.PAYLOAD_DISABLE_DEPENDENCY_CHECKER !== 'true' &&\n      !checkedDependencies\n    ) {\n      checkedDependencies = true\n      void checkPayloadDependencies()\n    }\n\n    this.importMap = options.importMap!\n\n    if (!options?.config) {\n      throw new Error('Error: the payload config is required to initialize payload.')\n    }\n\n    this.config = await options.config\n    this.logger = getLogger('payload', this.config.logger)\n\n    if (!this.config.secret) {\n      throw new Error('Error: missing secret key. A secret key is needed to secure Payload.')\n    }\n\n    this.encryptionKeyring = buildEncryptionKeyring([\n      this.config.secret,\n      ...(this.config.previousSecrets ?? []),\n    ])\n    this.secret = this.encryptionKeyring.active.legacyKey\n\n    this.globals = {\n      config: this.config.globals,\n    }\n\n    for (const collection of this.config.collections) {\n      let customIDType: string | undefined = undefined\n      const findCustomID: TraverseFieldsCallback = ({ field }) => {\n        if (\n          ['array', 'blocks', 'group'].includes(field.type) ||\n          (field.type === 'tab' && 'name' in field)","sourceCodeStart":905,"sourceCodeEnd":941,"githubUrl":"https://github.com/payloadcms/payload/blob/00c58b35c0ed348ddc22daabf467b139727214fd/packages/payload/src/index.ts#L905-L941","documentation":"Thrown right after the config resolves, when `this.config.secret` is falsy. Payload derives its encryption keyring (and the active legacy session key) from the secret, so an empty/undefined secret makes sessions, cookies, and field encryption insecure or non-functional. This is a deliberate security guard.","triggerScenarios":"Initializing Payload with a config whose `secret` is undefined, empty string, or null — typically because the env var backing it was not set in the current environment.","commonSituations":"Deploying without `PAYLOAD_SECRET` (or your custom env var); a `.env` file not loaded in the deployment; secret referenced via `process.env.PAYLOAD_SECRET` but the variable name differs; CI/preview environment missing the secret.","solutions":["Set a `secret` directly in buildConfig: `secret: process.env.PAYLOAD_SECRET`.","Ensure `PAYLOAD_SECRET` (32+ chars) is present in every environment (dev, CI, staging, prod).","Add a startup assertion that the secret is non-empty before init, to fail with a clearer message."],"exampleFix":"// before\nexport default buildConfig({ /* secret missing */ })\n\n// after\nexport default buildConfig({\n  secret: process.env.PAYLOAD_SECRET,\n})","handlingStrategy":"validation","validationCode":"const secret = process.env.PAYLOAD_SECRET\nif (!secret || secret.length < 32) {\n  throw new Error('PAYLOAD_SECRET must be set and at least 32 chars')\n}\n\nawait payload.init({ config, secret })","typeGuard":"function isValidSecret(value: string | undefined): value is string {\n  return typeof value === 'string' && value.length >= 32\n}\n\nif (!isValidSecret(process.env.PAYLOAD_SECRET)) {\n  throw new Error('Missing or weak PAYLOAD_SECRET')\n}","tryCatchPattern":"try {\n  await payload.init({ config, secret })\n} catch (err) {\n  if (err instanceof Error && err.message.includes('missing secret key')) {\n    // set PAYLOAD_SECRET in this environment and restart\n  }\n  throw err\n}","preventionTips":["Set PAYLOAD_SECRET in all environments (dev, CI, staging, prod) via your secret manager.","Add a pre-init assertion on secret presence and length.","Document the env var in the project README and CI config template."],"tags":["security","configuration","secret","startup"],"backgroundTag":null,"analyzedSha":"00c58b35c0ed348ddc22daabf467b139727214fd","analyzedAt":"2026-08-12T20:45:03.758Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}