localizeStatus: locale:'all' queries with _status where-clause silently return 0 docs; generated types don't reflect per-locale shape
Nobody has claimed this yet.
Assessment
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Newbie friendliness
- 58/100
- Issue type
- Bug
- Clarity
- Mostly clear
- Activity status
- Active
- Tech stack
- mongodb, typescript
Research direction
Start with the localizeStatus handling used by find/access queries and the payload generate:types entry point. Reproduce the MongoDB case from the configuration above, comparing locale: 'all' with an explicit locale and inspecting the generated _status type. Done means the query matches the intended localized documents and generated types reflect the localized status shape, with the documented behavior clarified if needed.
Written by the indexing model from the issue text.
Description
Describe the Bug
With experimental.localizeStatus enabled, _status becomes a per-locale field. Any find/access-control query that combines locale: 'all' with a where: { _status: { equals: 'published' } } filter — whether written explicitly or produced by an Access function returning a Where — silently returns zero matching documents, even though the documents genuinely have that status in every locale.
This breaks the common SSG pattern of fetching all locales of a collection in one query to build per-locale static params (generateStaticParams) or a multi-locale sitemap, gated by a public "published" access rule.
A secondary issue: the generated TypeScript types for _status are not updated when localizeStatus is enabled — they remain ('draft' | 'published') | null instead of reflecting the per-locale object shape actually returned by the API. Code can silently compare the object to a string and always get false, with no compile-time warning.
Link to reproduction
Minimal steps below reproduce it against any existing Payload 3.88.0 + MongoDB project; I can put together a standalone repro repo if useful.
To Reproduce
- Create a collection that is both localized and has drafts, e.g.:
export const Posts: CollectionConfig = { slug: 'posts', access: { read: () => ({ and: [ { _status: { equals: 'published' } }, { or: [{ publishedAt: { less_than_equal: new Date() } }, { publishedAt: { exists: false } }] }, ], }), }, versions: { drafts: { localizeStatus: true }, }, fields: [{ name: 'title', type: 'text', localized: true }], } - In
payload.config.ts, set:experimental: { localizeStatus: true } - Publish a document (status becomes
publishedfor the active locale). - Query it with
locale: 'all'and the same published-only condition:await payload.find({ collection: 'posts', draft: false, overrideAccess: false, // or overrideAccess: true with an explicit `where: { _status: { equals: 'published' } } }` locale: 'all', }) - Observe
totalDocs: 0. - Now query the same document with a single explicit locale (
locale: 'it') instead of'all'— it is found correctly, and_statuscomes back as{ it: 'published', en: 'published' }(an object, not a string).
Expected behavior
- A
where: { _status: { equals: 'published' } }filter combined withlocale: 'all'should match documents where any locale (or a clearly documented specific locale) has that status — not silently match nothing. At minimum this should be called out prominently in thelocalizeStatusdocs, since it's a correctness footgun for exactly the "build-time SSG across all locales" use case per-locale status is meant to support. payload generate:typesshould reflect the per-locale shape of_status(e.g.Partial<Record<Locale, 'draft' | 'published'>>) for any collection whereversions.drafts.localizeStatusis enabled, instead of always emitting('draft' | 'published') | null.
Payload Version
3.88.0
Adapter
MongoDB (@payloadcms/db-mongodb)
OS
macOS
Node Version
24.14.0
Package Manager
pnpm 10.5.2
Before submitting
- I have searched the existing issues and this is not a duplicate
- I agree to follow this project's Code of Conduct
- Dominant language
- TypeScript
- Stars
- 44.8k
- Forks
- 4.2k
- Avg merge
- 2d 21h
- Merged PRs (30d)
- 53
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from payloadcms/payload
-
area: ui Bug status: needs-triage v3
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
payloadcms/payload#18215 · 1 comment ·
-
Bug
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
payloadcms/payload#18163 ·
-
Bug
Difficulty 2/5 1-3 hours Newbie friendliness 85/100
payloadcms/payload#18161 ·
-
area: core Bug
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
payloadcms/payload#18072 ·
-
Bug
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
payloadcms/payload#18067 · 1 comment ·
All issues in payloadcms/payload
Similar issues
-
clawsweeper:fix-shape-clear clawsweeper:queueable-fix clawsweeper:source-repro impact:ux-friction issue-rating: 🦞 diamond lobster no-stale P3
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
-
community first-timers-only good first issue hacktoberfest help wanted low hanging fruit up-for-grabs
Difficulty 1/5 Under an hour Newbie friendliness 76/100
-
code-quality refactoring
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
github/gh-aw-firewall#8816 ·
-
integration:quickjs org:external priority:backlog topic:code-interpreter topic:middleware type:feature
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
langchain-ai/deepagents#6450 ·
-
Difficulty 1/5 Under an hour Newbie friendliness 88/100
vercel/react-tweet#225 ·