obsidian/wiki/concepts/payload-cms-root-layout-requirement.md
2026-05-10 21:26:56 +01:00

2 KiB

title source updated tags
Payload CMS 3.x — (payload)/layout.tsx Must Use RootLayout daily/2026-05-10.md 2026-05-10
payload-cms
nextjs
cms
crash

Payload CMS 3.x — (payload)/layout.tsx Must Use RootLayout

Problem

In a Payload CMS 3.x + Next.js project, leaving (payload)/layout.tsx empty (or as a pass-through layout) causes the Payload admin panel to crash with a cryptic 500 error:

TypeError: Cannot destructure property 'config' of undefined

The error traces into Payload internals and gives no indication that the layout file is the cause.

Fix

(payload)/layout.tsx must import and render RootLayout from @payloadcms/next/layouts:

// app/(payload)/layout.tsx
import React from 'react'
import { RootLayout } from '@payloadcms/next/layouts'
import { importMap } from './admin/importMap'
import config from '@payload-config'

type Args = {
  children: React.ReactNode
}

const Layout = ({ children }: Args) => (
  <RootLayout config={config} importMap={importMap}>
    {children}
  </RootLayout>
)

export default Layout

handleServerFunctions wrapper (for server actions) must be inside a 'use server' block:

// app/(payload)/actions.ts
'use server'
import { handleServerFunctions } from '@payloadcms/next/utilities'
export { handleServerFunctions }

Turbopack incompatibility

Payload CMS 3.x is incompatible with Turbopack (Next.js 15 default dev server). The dev script must use --webpack:

"dev": "next dev --webpack"

Without this, hot-reload breaks and some Payload UI features fail silently.

next lint removed in Next.js 16

next lint was removed in Next.js 16. Use ESLint directly:

eslint src/

The lint script in package.json must be updated accordingly.

Why It Happens

Payload CMS injects its context (config, importMap) into the Next.js layout tree. Without RootLayout, the context provider is never mounted, so every Payload component that tries to read the context gets undefined.