Skip to content

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

Description

@MurzNN

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    area: coreCore Payload functionalitystatus: needs-triagePossible bug which hasn't been reproduced yetv3

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions