{"record":{"id":"38841d7ce5b9845f","repo":"payloadcms/payload","slug":"storage-contains-an-invalid-entry-expected-an-obj","errorCode":null,"errorMessage":"storage contains an invalid entry: expected an object with an `init` function. Ensure you are passing the result of a storage adapter factory (e.g. s3Storage({…})) to `storage`, not to `plugins`.","messagePattern":"storage contains an invalid entry: expected an object with an `init` function\\. Ensure you are passing the result of a storage adapter factory \\(e\\.g\\. s3Storage\\((.+?)\\)\\) to `storage`, not to `plugins`\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/payload/src/config/build.ts","lineNumber":22,"sourceCode":"\n/**\n * @description Builds and validates Payload configuration\n * @param config Payload Config\n * @returns Built and sanitized Payload Config\n */\nexport async function buildConfig(config: Config): Promise<SanitizedConfig> {\n  if (Array.isArray(config.plugins)) {\n    const sorted = [...config.plugins].sort((a, b) => (a.order ?? 0) - (b.order ?? 0))\n\n    for (const plugin of sorted) {\n      config = await plugin(config)\n    }\n  }\n\n  if (Array.isArray(config.storage)) {\n    for (const adapter of config.storage) {\n      if (typeof adapter?.init !== 'function') {\n        throw new Error(\n          `storage contains an invalid entry: expected an object with an \\`init\\` function. ` +\n            `Ensure you are passing the result of a storage adapter factory (e.g. s3Storage({…})) ` +\n            `to \\`storage\\`, not to \\`plugins\\`.`,\n        )\n      }\n      config = await adapter.init(config)\n    }\n  }\n\n  return sanitizeConfig(config)\n}\n","sourceCodeStart":4,"sourceCodeEnd":34,"githubUrl":"https://github.com/payloadcms/payload/blob/00c58b35c0ed348ddc22daabf467b139727214fd/packages/payload/src/config/build.ts#L4-L34","documentation":"Thrown at config build time when an entry in `config.storage` does not expose an `init` function. Storage adapters must be the result of a factory call (e.g. `s3Storage({…})`) that returns `{ init }`. The check exists because a common mistake is placing the adapter in `plugins` or passing the raw options object instead of the constructed adapter.","triggerScenarios":"Passing `s3Storage` (the factory) instead of `s3Storage({...})` (its result) to `storage`; pushing a storage adapter into the `plugins` array by mistake; passing `{ bucket: 'x' }` options object directly to `storage`.","commonSituations":"Migrating from the old upload-adapter API to the v3 `storage` config; copy-paste from a plugin example into the storage slot; forgetting to call the factory.","solutions":["Move the adapter from `plugins` into the `storage` array.","Ensure each storage entry is a factory invocation, e.g. `storage: [s3Storage({ bucket: 'x' })]`, not the bare options or the function reference.","If writing a custom adapter, return an object whose `init` is an async `(config) => config`."],"exampleFix":"// before\nbuildConfig({ plugins: [s3Storage({ bucket: 'x' })] })\n// after\nimport { s3Storage } from '@payloadcms/storage-s3'\nbuildConfig({ storage: [s3Storage({ bucket: 'x' })] })","handlingStrategy":"type-guard","validationCode":"import { buildConfig } from 'payload'\nconst storage = [s3Storage({ bucket: 'x' })]\nif (!Array.isArray(storage) || storage.some((a) => typeof a?.init !== 'function')) {\n  throw new Error('Every storage entry must be a factory result with an init() function')\n}\nawait buildConfig({ storage })","typeGuard":"import type { StorageAdapter } from 'payload'\nfunction isStorageAdapter(a: unknown): a is StorageAdapter {\n  return typeof a === 'object' && a !== null && typeof (a as any).init === 'function'\n}\n// assert: if (!storage.every(isStorageAdapter)) throw","tryCatchPattern":null,"preventionTips":["Always call the factory: `s3Storage({...})`, never pass the options object or the function itself.","Put adapters in `storage`, never in `plugins`.","When writing a custom adapter, return `{ init: async (config) => config }`."],"tags":["config","storage","upload","buildconfig","adapter"],"backgroundTag":null,"analyzedSha":"00c58b35c0ed348ddc22daabf467b139727214fd","analyzedAt":"2026-08-12T20:45:03.758Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}