Bug description
When you switch an entry to another localization in the CP, the "unsaved changes" prompt sometimes appears afterwards, although nothing was edited. For example, you switch DE → FR and then back to DE.
The cause is the assets watcher in AssetsFieldtype.vue. It calls this.update() without any condition:
// resources/js/components/fieldtypes/assets/AssetsFieldtype.vue
assets: {
deep: true,
handler(assets) {
if (this.initializing) return;
this.update(this.assetIds); // always emits, even if the IDs didn't change
...
What happens on a localization switch:
editLocalization() replaces values and disables dirty tracking for 500ms (trackDirtyStateTimeout).
- The
value watcher sees new asset IDs and calls loadAssets(), which sends a POST to /cp/assets-fieldtype.
- When that request resolves after the 500ms window,
this.assets is set. The assets watcher then emits update() with a new array that has the same IDs.
- The Publish Container's deep
values watcher calls Statamic.$dirty.add(), so the entry is marked dirty although the values are unchanged.
We confirmed this with a debug log in the Container. The diff between the previous and the new values was empty when the entry got marked dirty, and the stack trace goes through loadAssets.
Whether it happens depends on how long the request takes. That makes it look random for editors.
Suggested fix
Only emit when the IDs differ. isEqual is already imported, and the value watcher uses the same check:
handler(assets) {
if (this.initializing) return;
if (! isEqual(this.value, this.assetIds)) {
this.update(this.assetIds);
}
...
We patched this into the compiled bundle locally, and it fixes the issue. Adding, removing and reordering assets still marks the entry dirty as expected.
How to reproduce
- Set up a multisite with at least two sites.
- Create an entry with an
assets field, e.g. nested in Replicator sets, where the localizations reference different assets.
- Edit the origin entry in the CP and switch to the other localization, then switch back.
- The "unsaved changes" prompt appears although nothing was edited.
It doesn't happen every time. It only happens when the /cp/assets-fieldtype request takes longer than the 500ms dirty-tracking window, so it's more likely with several assets fields on the page. To reproduce it reliably, throttle the network in DevTools (e.g. "Slow 4G") before switching.
Logs
Environment
Environment
Laravel Version: 12.64.0
PHP Version: 8.4.26
Composer Version: 2.9.5
Environment: local
Debug Mode: ENABLED
Maintenance Mode: OFF
Timezone: UTC
Locale: de
Cache
Config: NOT CACHED
Events: NOT CACHED
Routes: NOT CACHED
Views: CACHED
Drivers
Broadcasting: log
Cache: redis
Database: mysql
Logs: stack / daily
Mail: smtp
Queue: redis
Session: redis
Statamic
Addons: 4
License Key: Not set
Sites: 3 (Deutsch, Français, Italiano)
Stache Watcher: Enabled (auto)
Static Caching: Disabled
Version: 6.34.1 PRO
Statamic Addons
rias/statamic-redirect: 4.1.12
teamnovu/graphql-breadcrumbs: 1.0.8
teamnovu/localize: 6.0.21
teamnovu/statamic-gql-swr-cache: 6.11.0.1
Installation
Existing site that has been upgraded from earlier Statamic versions over time (not a fresh install). We haven't reproduced this on a fresh install yet.
Additional details
Related: #15484. The relationship SelectField crash on localization switch happens in the same flow and also leaves the form dirty.
Bug description
When you switch an entry to another localization in the CP, the "unsaved changes" prompt sometimes appears afterwards, although nothing was edited. For example, you switch DE → FR and then back to DE.
The cause is the
assetswatcher inAssetsFieldtype.vue. It callsthis.update()without any condition:What happens on a localization switch:
editLocalization()replacesvaluesand disables dirty tracking for 500ms (trackDirtyStateTimeout).valuewatcher sees new asset IDs and callsloadAssets(), which sends a POST to/cp/assets-fieldtype.this.assetsis set. Theassetswatcher then emitsupdate()with a new array that has the same IDs.valueswatcher callsStatamic.$dirty.add(), so the entry is marked dirty although the values are unchanged.We confirmed this with a debug log in the Container. The diff between the previous and the new
valueswas empty when the entry got marked dirty, and the stack trace goes throughloadAssets.Whether it happens depends on how long the request takes. That makes it look random for editors.
Suggested fix
Only emit when the IDs differ.
isEqualis already imported, and thevaluewatcher uses the same check:We patched this into the compiled bundle locally, and it fixes the issue. Adding, removing and reordering assets still marks the entry dirty as expected.
How to reproduce
assetsfield, e.g. nested in Replicator sets, where the localizations reference different assets.It doesn't happen every time. It only happens when the
/cp/assets-fieldtyperequest takes longer than the 500ms dirty-tracking window, so it's more likely with several assets fields on the page. To reproduce it reliably, throttle the network in DevTools (e.g. "Slow 4G") before switching.Logs
Environment
Installation
Existing site that has been upgraded from earlier Statamic versions over time (not a fresh install). We haven't reproduced this on a fresh install yet.
Additional details
Related: #15484. The relationship
SelectFieldcrash on localization switch happens in the same flow and also leaves the form dirty.