-
Notifications
You must be signed in to change notification settings - Fork 3k
Description
Describe the Bug
Field hooks (beforeValidate
, beforeChange
, afterChange
, beforeDuplicate
) do not execute for relationship fields that are defined within blocks embedded in Lexical rich text fields.
Only the afterRead
hook fires correctly.
This prevents:
- Field validation from running (data integrity issues)
- Data transformation in beforeChange hooks
- Side effects in afterChange hooks (notifications, derived data, etc.)
- Custom duplication logic in beforeDuplicate hooks (I suppose duplicating a block like this feels uncommon though)
Expected Behavior
All field hooks should fire for relationship fields regardless of where they are defined, just as they do for direct relationship fields on collections.
Actual Behavior
For relationship fields in blocks within Lexical fields:
- ✗
beforeValidate
- does NOT fire - ✗
beforeChange
- does NOT fire - ✗
afterChange
- does NOT fire - ✓
afterRead
- fires correctly - ✗
beforeDuplicate
- does NOT fire
Link to the code that reproduces this issue
https://github.com/busbyk/field-hooks-in-lexical-reproduction
Reproduction Steps
Reproduction Steps:
- Clone the reproduction repository
- Install dependencies:
pnpm install
- Copy environment variables:
cp .env.example .env
- Generate types:
pnpm run generate:types
- Run the integration tests:
pnpm run test:int tests/int/field-hooks.int.spec.ts
Expected Result
All tests should pass - all hooks should fire for both direct relationship fields and block relationship fields.
Actual Result
Control tests pass (direct relationship fields work correctly), but 2 of 3 block relationship field tests fail:
✓ Direct Relationship Fields (Control) - All hooks fire
✓ should fire beforeValidate, beforeChange, and afterChange hooks on create
✓ should fire afterRead hook on read
✓ should fire beforeDuplicate hook on duplicate
✗ Block Relationship Fields in Lexical (BUG)
✗ should fire beforeValidate, beforeChange, and afterChange hooks on create
✓ should fire afterRead hook on read (ONLY ONE THAT WORKS)
✗ should fire beforeDuplicate hook on duplicate
The test output clearly shows that for blocks in Lexical fields, only afterRead
hooks fire. All "write-path" hooks are bypassed.
Which area(s) are affected? (Select all that apply)
plugin: richtext-lexical
Environment Info
Binaries:
Node: 22.14.0
npm: 11.2.0
Yarn: N/A
pnpm: 10.14.0
Relevant Packages:
payload: 3.59.1
next: 15.4.4
@payloadcms/db-sqlite: 3.59.1
@payloadcms/drizzle: 3.59.1
@payloadcms/email-nodemailer: 3.59.1
@payloadcms/graphql: 3.59.1
@payloadcms/next/utilities: 3.59.1
@payloadcms/payload-cloud: 3.59.1
@payloadcms/richtext-lexical: 3.59.1
@payloadcms/translations: 3.59.1
@payloadcms/ui/shared: 3.59.1
react: 19.1.0
react-dom: 19.1.0
Operating System:
Platform: darwin
Arch: arm64
Version: Darwin Kernel Version 24.6.0: Mon Jul 14 11:30:40 PDT 2025; root:xnu-11417.140.69~1/RELEASE_ARM64_T6041
Available memory (MB): 24576
Available CPU cores: 14