payloadcms / payloadcms/payload

Field's `defaultValue` applied to all locales instead of the current locale only

Open
#17,406 2 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

area: core status: needs-triage v3
Dominant language
TypeScript
Stars
44.8k
Forks
4.2k
Avg merge
2d 21h
Merged PRs (30d)
53

Description

Describe the Bug

When a localized collection field has a defaultValue configured, the default value is applied to all locales during document creation or update operations, instead of only to the locale being operated on. Fields that should only have default values for the current locale end up with default values for all configured locales.

Locale-aware default value logic exists in the afterRead hook, but the same locale-specific handling is not consistently applied during the beforeChange lifecycle stage where data is populated during create/update operations. Reading an unwritten locale (e.g. es after creating in en) can return the field's default value even when fallbackLocale: false is set.

Example configuration:

{
  name: 'myField',
  type: 'text',
  localized: true,
  defaultValue: 'Default Value', // or a function: ({ locale }) => `default-${locale}`
}

Proposed Fix

Ensure defaultValue is applied only to the current locale during create/update operations, following the pattern used in afterRead where getDefaultValue is called with the locale parameter:

  1. Modify the beforeChange hook logic to apply defaultValue with locale awareness
  2. When a localized field has a defaultValue, only populate the value for the specific locale being operated on
  3. Call getDefaultValue with the current locale context during write operations, not just during read operations

Relevant code:

  • packages/payload/src/fields/hooks/afterRead/promise.ts — locale-aware getDefaultValue on read
  • packages/payload/src/fields/hooks/beforeValidate/getFallbackValue.ts — applies defaultValue without locale-specific write handling
  • packages/payload/src/fields/hooks/beforeChange/promise.ts — locale unflattening during writes

Workaround

Create/update with a specific locale and apply remaining locales through subsequent update operations (see import-export plugin pattern):

await payload.create({
  collection: 'your-collection',
  data: flatData,
  locale: 'en',
})

await payload.update({
  collection: 'your-collection',
  id: docId,
  data: localeData,
  locale: 'es',
})
Link to the code that reproduces this issue

https://github.com/MurzNN/payload/tree/repro/localized-default-value

Reproduction Steps
  1. Configure a collection with localization enabled (multiple locales) and fallback: false

  2. Add a localized field with defaultValue (static string or function)

  3. Create a document with a specific locale (e.g. en) without providing the field value:

    await payload.create({
      collection: 'localized-default-value-posts',
      data: { title: 'English title' },
      locale: 'en',
    })
    
  4. Query the document with locale: 'all' and observe that defaultValue appears for locales that were never written (e.g. es)

  5. Query the document with locale: 'es' and fallbackLocale: false — the field still returns the default value instead of undefined

Expected: defaultValue is stored and returned only for the locale used in the create/update operation.

Actual: defaultValue is applied across locales that were not part of the operation.

Reproduction in the branch: run: pnpm test:int localized-default-value

Which area(s) are affected?

area: core

Environment Info
Binaries:
  Node: 24.18.0
  npm: 11.16.0
  Yarn: N/A
  pnpm: 11.1.3
Relevant Packages:
  payload: 3.85.2
  next: 16.2.6
  @payloadcms/db-mongodb: 3.85.2
  @payloadcms/graphql: 3.85.2
  @payloadcms/live-preview: 3.85.2
  @payloadcms/live-preview-react: 3.85.2
  @payloadcms/next/utilities: 3.85.2
  @payloadcms/plugin-import-export: 3.85.2
  @payloadcms/plugin-nested-docs: 3.85.2
  @payloadcms/plugin-redirects: 3.85.2
  @payloadcms/plugin-search: 3.85.2
  @payloadcms/plugin-seo: 3.85.2
  @payloadcms/richtext-lexical: 3.85.2
  @payloadcms/sdk: 3.85.2
  @payloadcms/translations: 3.85.2
  @payloadcms/ui/shared: 3.85.2
  react: 19.2.7
  react-dom: 19.2.7
Operating System:
  Platform: linux
  Arch: x64
  Version: #27-Ubuntu SMP PREEMPT_DYNAMIC Thu Jun 18 19:13:49 UTC 2026
  Available memory (MB): 31515
  Available CPU cores: 16

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/fields/hooks/beforeValidate/getFallbackValue.ts and packages/payload/src/fields/hooks/beforeChange/promise.ts, then compare their behavior with the locale-aware handling in packages/payload/src/fields/hooks/afterRead/promise.ts. Run pnpm test:int localized-default-value against the reproduction branch. Done means a localized default is written and returned only for the locale used in the create or update, including when fallbackLocale is false.

Written by the indexing model from the issue text.

Assessment

Tech stack
nodejs, typescript
Domain
backend, localization
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
72/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.