payloadcms / payloadcms/payload

hierarchy: afterRead hook uses doc._status instead of request draft intent when computing paths

Open
#17,223 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

created-by: Contributor
Dominant language
TypeScript
Stars
44.8k
Forks
4.2k
Avg merge
2d 21h
Merged PRs (30d)
53

Description

Describe the Bug

In packages/payload/src/hierarchy/hooks/collectionAfterRead.ts, the draft flag passed to computePaths is derived from the document's own _status:

draft: doc._status === 'draft',

This is incorrect. doc._status reflects whether this specific document has unpublished changes — it does not reflect the request's draft intent (e.g. draft: true in the local API or ?draft=true in the REST API / live preview).

Broken scenario:

  1. Parent page: published slug "about", draft slug "about-us" (draft saved but not published)
  2. Child page: no pending draft changes → _status: 'published'
  3. User opens child in live preview (draft: true)
  4. doc._status === 'draft' is false for the child → computePaths receives draft: false → fetches the published parent → breadcrumb shows "about/child" instead of "about-us/child"

The user is in draft/preview mode and expects the entire path tree to reflect draft state, but doc._status only tells you about the document itself, not the request's intent.

The root cause is that draft is not currently available as a hook argument, so there is no clean way to derive the request's draft intent from within afterRead. A proper fix requires exposing draft in the hook args — see: https://github.com/payloadcms/payload/issues/16180

Link to the code that reproduces this issue

https://github.com/jhb-software/payload-issue-reproductions/tree/main/hierarchy-afterread-wrong-draft-context/

Reproduction Steps

  1. Clone the repo / open the folder hierarchy-afterread-wrong-draft-context/
  2. pnpm install
  3. pnpm test:int — the test fails, proving the bug

Which area(s) are affected?

  • plugin: hierarchy

Environment Info

Binaries:
  Node: 24.16.0
  npm: 11.13.0
  Yarn: 1.22.22
  pnpm: 11.9.0
Relevant Packages:
  payload: 4.0.0-internal.e16cf59
  @payloadcms/db-sqlite: 4.0.0-internal.e16cf59
  @payloadcms/drizzle: 4.0.0-internal.e16cf59
  @payloadcms/translations: 4.0.0-internal.e16cf59
Operating System:
  Platform: linux
  Arch: x64
  Version: #134-Ubuntu SMP PREEMPT_DYNAMIC Fri Jun 26 18:43:11 UTC 2026
  Available memory (MB): 3916
  Available CPU cores: 1

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with packages/payload/src/hierarchy/hooks/collectionAfterRead.ts and review how hook arguments are exposed, alongside the design referenced in issue #16180. Reproduce the failure from hierarchy-afterread-wrong-draft-context/ with pnpm test:int. Done means the failing test passes and preview paths use the request's draft intent for the parent tree.

Written by the indexing model from the issue text.

Assessment

Tech stack
nodejs, typescript
Domain
api, backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
52/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.