Skip to content

fix: isolate locale properties in createLocalReq - #18280

Open
Dextheking1 wants to merge 2 commits into
payloadcms:mainfrom
Dextheking1:fix/payload-18246-locale-isolation
Open

Dextheking1 wants to merge 2 commits into
payloadcms:mainfrom
Dextheking1:fix/payload-18246-locale-isolation

Conversation

@Dextheking1

@Dextheking1 Dextheking1 commented Sep 24, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #18246.

Problem

A Local API call made inside a field validate, a relationship filterOptions, or a beforeChange hook normally passes the operation's req. If that call also passes a locale different from the operation's, createLocalReq wrote that locale (and the recomputed fallbackLocale) onto the caller's req object. beforeChange merges submitted single-locale data into the per-locale document in deferred mergeLocaleActions that read req.locale after every field's hooks/validation have awaited, so the submitted values were merged into the nested call's locale instead of the operation's, silently corrupting localized data (see the issue's en/es repro).

Root cause

createLocalReq (packages/payload/src/utilities/createLocalReq.ts) assigned req.locale / req.fallbackLocale directly on the passed-in object.

Fix

Wrap the incoming req with isolateObjectProperty(req, ['locale', 'fallbackLocale']), the same pattern restoreVersion already uses (option 1 from the issue). The nested operation still sees its own locale through the returned request; the caller's object keeps its original values. All other callers use the return value, so no side-effect behavior changes.

Testing

  • Added createLocalReq - locale isolation suite in packages/payload/src/utilities/createLocalReq.spec.ts:
    • nested call with a different locale does not rewrite the caller's req.locale (returned request carries the nested locale)
    • caller's req.fallbackLocale is not rewritten
    • no explicit locale falls back to the caller's req.locale
  • Verified the two mutation tests fail before the fix and pass after; all 6 pre-existing URL tests still pass.
  • isolateObjectProperty.spec.ts + createLocalReq.spec.ts: 18 passed.
  • tsc --noEmit on packages/payload: no new errors (104 pre-existing TS6305 project-reference errors on baseline and with the change).

Fixes payloadcms#18246.

A Local API call that passes both `req` and a different `locale` rewrote
the caller's `req.locale`/`req.fallbackLocale` in place. `beforeChange`
merges submitted data into per-locale fields based on `req.locale` after
hooks/validation have awaited, so the nested call's locale corrupted the
parent operation's data (submitted values merged into the wrong locale).

Wrap the incoming req with `isolateObjectProperty(req, ['locale',
'fallbackLocale'])` (the same pattern `restoreVersion` already uses) so
the nested operation sees its own locale through the returned request
while the caller's object keeps its original values.
@Dextheking1 Dextheking1 changed the title fix(payload): isolate locale properties in createLocalReq fix: isolate locale properties in createLocalReq Sep 24, 2026
@Dextheking1
Dextheking1 marked this pull request as ready for review September 24, 2026 16:33
@Dextheking1

Copy link
Copy Markdown
Contributor Author

Rebased onto current main. Upstream consolidated createLocalReq into createPayloadRequest in #18287, so the locale isolation fix is ported there (same proxy approach, same tests).

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Nested Local API call with req + a different locale rewrites the parent operation's req.locale, so a save's localized values land in the wrong locale

1 participant