---
title: "Payload CMS + Node 26 — Seed Script ESM Workaround"
source: daily/2026-05-10.md
updated: 2026-05-10
tags: [payload-cms, nextjs, nodejs, esm, seed]
---

# Payload CMS + Node 26 — Seed Script ESM Workaround

## Problem

Running a Payload CMS seed script directly via `npx tsx seed.ts` on **Node 26** fails with:

```
ERR_REQUIRE_ESM: require() of ES Module ... not supported
```

or module resolution errors because Node 26's stricter ESM/CJS interop breaks the way Payload loads its config and collections outside a Next.js process.

## Fix: Seed via API Route

Instead of a standalone script, expose seed logic as a Next.js API route and call it from a running dev server:

```ts
// app/api/seed/route.ts
import { getPayload } from 'payload'
import config from '@payload-config'
import { NextResponse } from 'next/server'

export async function GET() {
  const payload = await getPayload({ config })

  // Check if already seeded
  const existing = await payload.find({ collection: 'users', limit: 1 })
  if (existing.totalDocs > 0) {
    return NextResponse.json({ message: 'Already seeded' })
  }

  await payload.create({
    collection: 'users',
    data: {
      email: 'admin@example.com',
      password: 'changeme',
      role: 'admin',
    },
  })

  return NextResponse.json({ message: 'Seeded successfully' })
}
```

Then seed by hitting `http://localhost:3000/api/seed` while the dev server is running.

## Why This Works

The API route runs **inside the already-running Next.js process** which has already resolved all ESM/CJS module boundaries correctly. `getPayload({ config })` reuses the singleton Payload instance without a standalone boot sequence.

## Future

Remove this workaround once Payload officially supports Node 26 module resolution. The standalone seed approach (`payload/dist/bin/seed`) is cleaner but requires ESM-stable Node.
