localizeStatus: locale:'all' queries with _status where-clause silently return 0 docs; generated types don't reflect per-locale shape

Open
#17,923 1 comment 0 reactions 0 assignees View on GitHub

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

  1. 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 }],
    }
    
  2. In payload.config.ts, set:
    experimental: { localizeStatus: true }
    
  3. Publish a document (status becomes published for the active locale).
  4. 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',
    })
    
  5. Observe totalDocs: 0.
  6. Now query the same document with a single explicit locale (locale: 'it') instead of 'all' — it is found correctly, and _status comes back as { it: 'published', en: 'published' } (an object, not a string).

Expected behavior

  • A where: { _status: { equals: 'published' } } filter combined with locale: '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 the localizeStatus docs, 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:types should reflect the per-locale shape of _status (e.g. Partial<Record<Locale, 'draft' | 'published'>>) for any collection where versions.drafts.localizeStatus is 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

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.

More from payloadcms/payload

All issues in payloadcms/payload

Similar issues

More TypeScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.