Skip to content

fix(ui): resolve globals correctly in copyDataFromLocale#16334

Open
robinvandenb wants to merge 1 commit intopayloadcms:mainfrom
robinvandenb:fix-copy-to-locale-global
Open

fix(ui): resolve globals correctly in copyDataFromLocale#16334
robinvandenb wants to merge 1 commit intopayloadcms:mainfrom
robinvandenb:fix-copy-to-locale-global

Conversation

@robinvandenb
Copy link
Copy Markdown

The bug

Calling the server function copyDataFromLocaleHandler with a globalSlug (triggered by the admin UI's "Copy to locale" button on any Global) crashes with:

TypeError: Cannot read properties of undefined (reading 'config')
    at copyDataFromLocale (packages/ui/src/utilities/copyDataFromLocale.ts:208)

The same button works fine for Collections. For Globals it is 100% broken. Reproducible on current main and released versions up to at least v3.83.0.

Repro steps

  1. In any config with localization enabled and ≥ 2 locales, define a Global (e.g. { slug: 'homescreen-layout', fields: [...] }).
  2. Edit the Global in one locale, save.
  3. Switch to another locale, open the "Copy to locale" menu, pick the source locale, click "Copy".
  4. Observe the error above in server logs; the admin toast shows "Cannot read properties of undefined (reading 'config')".

Root cause

copyDataFromLocale destructured globals off req.payload and then looked up globals[globalSlug].config.fields, assuming payload.globals is a slug-keyed map the way payload.collections is. It isn't. Per packages/payload/src/index.ts, payload.globals always has shape { config: SanitizedGlobalConfig[] }. Every other place in the codebase (e.g. packages/payload/src/globals/operations/local/findOne.ts, update.ts, restoreVersion.ts, findVersions.ts, findVersionByID.ts, countVersions.ts, utilities/handleEndpoints.ts, utilities/getRequestEntity.ts) resolves a global via payload.globals.config.find((c) => c.slug === globalSlug). copyDataFromLocale was the only offender, so globals[globalSlug] was always undefined for a real slug and .config threw.

The fix

  • Look up the global via payload.globals.config.find((c) => c.slug === globalSlug), matching the rest of Payload.
  • Throw APIError("The global with slug X can't be found.", 404) if the slug is missing (mirrored the same guard on the collection branch so a bad collectionSlug no longer crashes on undefined.config.fields either).
  • Removed the unused globals destructure.

Public signatures of copyDataFromLocale / copyDataFromLocaleHandler are unchanged.

Tests

Added under test/localization/int.spec.ts, inside the existing Copying To Locale block:

  • copies undefined fields from a source locale to a target locale on a global — seeds en, clears es, calls copyDataFromLocaleHandler with globalSlug, asserts title and group.subtitle are copied on the es draft. This would have failed on main with the original TypeError.
  • throws a clear error when the global slug does not exist — asserts the new APIError path.

Introduced a minimal localized-global-for-copy global in test/localization/config.ts for the round-trip.

Run locally with:

pnpm test:int --filter localization

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.

1 participant