Skip to content

[6.x] New Asset Exists Modal Resolution Feature#14433

Open
jackmcdade wants to merge 5 commits into6.xfrom
asset-exists-modal
Open

[6.x] New Asset Exists Modal Resolution Feature#14433
jackmcdade wants to merge 5 commits into6.xfrom
asset-exists-modal

Conversation

@jackmcdade
Copy link
Copy Markdown
Member

@jackmcdade jackmcdade commented Apr 3, 2026

Works with uploading and moving assets. Resolves #14381.

asset-conflicts.mp4

Note

Medium Risk
Touches both CP frontend and backend action/upload flows to introduce new 409 conflict responses and resolution strategies; mistakes could cause unintended overwrites or stuck uploads/moves, though changes are scoped and covered by tests for move conflicts.

Overview
Adds first-class asset conflict resolution for both uploads and drag/drop moves in the CP.

Conflicting uploads now return structured 409 JSON with conflict details, the browser queues these conflicts and presents a modal to Cancel, Keep Both (timestamp), or Overwrite, with optional apply to all, and cache-busts affected previews/thumbnails after overwrite/timestamp resolutions.

Conflicting moves now detect existing destination files in MoveAsset, throw an AssetConflictException with conflict metadata, and the asset browser intercepts this to show the same modal flow (including multi-selection handling, optional apply-to-all policy, and glide cache clearing on overwrite).

Reviewed by Cursor Bugbot for commit ad6f0b2. Bugbot is set up for automated code reviews on this repo. Configure here.

Works with uploading and moving assets. Resolves #14381.
}

$ids[] = $asset->move($folder)->id();
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Partially moved assets cause stale IDs on retry

High Severity

When moving multiple assets, the run() method moves them sequentially and throws AssetConflictException on the first conflict. Assets moved before the conflict are not rolled back — their IDs change because their paths change. However, pendingSelections on the client still holds the original (now stale) IDs for those already-moved assets. When continueMoveConflictResolution re-sends those stale IDs in the next request, the server fails to resolve them, causing errors or silently losing track of those assets.

Additional Locations (1)
Fix in Cursor Fix in Web

This updates the asset conflict UX by making modal-dismiss behavior resolve as cancel, only showing “apply to all” when multiple upload conflicts exist, and replacing recursive move-conflict continuation with an iterative loop. It also adds MoveAsset tests for non-conflicting moves, same-folder no-op moves, and explicit cancel strategy handling.
Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

There are 2 total unresolved issues (including 1 from previous review).

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit ad6f0b2. Configure here.

: __('statamic::messages.asset_conflict_a_newer');
$existingAge = $sourceLastModified >= $destinationLastModified
? __('statamic::messages.asset_conflict_older')
: __('statamic::messages.asset_conflict_newer');
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused $existingAge variable computed but never displayed

Low Severity

The $existingAge variable is computed and passed as the :existing_age replacement to the translation message, but the asset_conflict_message template string doesn't contain an :existing_age placeholder. This is dead code that adds confusion about whether the message was intended to include this information.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit ad6f0b2. Configure here.

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.

Moving assets into a subfolder silently overwrites existing files

1 participant