Skip to content

Image Editor reload appends stacking cache timestamp and doesn't reflect edits behind a CDN #595

Description

@suprim-simple

Description

When you edit an image with the asset Image Editor from inside a CKEditor field, _reloadImage() in src/web/assets/ckeditor/src/image/imageeditor/imageeditorcommand.js builds a cache-busted src from srcInfo.baseSrc. But baseSrc comes from the greedy (.*) in _srcInfo()'s regex:

const match = src.match(/(.)#asset:(\d+)(?::transform:([a-zA-Z][a-zA-Z0-9_]))?/);
// baseSrc = match[1] → everything before "#asset:", INCLUDING any existing query
So baseSrc already contains the previously-appended ?, and _reloadImage() appends another one each time:

let newSrc = image.srcInfo.baseSrc + '?' + new Date().getTime() + '#asset:' + image.srcInfo.assetId;
The query string stacks on every edit, producing malformed URLs (a URL can only have one ?):

…/MT-3_2026-06-09-020259_hbsn.jpeg?0?1780971727673?1780971779690?1780971926837#asset:1395663
This stacked URL is then persisted into the stored field content.

A second, related problem: even with a single valid cache-buster, the editor swaps the src immediately on save with no allowance for CDN propagation. When assets are served through a CDN that caches by path / doesn't vary on the query string and invalidates asynchronously (e.g. CloudFront + AWS Serverless Image Handler, which is a very common Craft setup), the reload fetches the still-cached pre-edit image, so the edit doesn't visibly update — often requiring repeated saves or a hard refresh.

For reference, Craft core avoids this for its own thumbnails by deriving a stable, content-based buster from the asset's modified time (AssetsHelper::revUrl() / revParams() → ?v=), rather than appending a fresh timestamp onto whatever is already in the src.

imageeditorcommand.js

Steps to reproduce

  • Insert an image asset into a CKEditor field and save the entry.
  • Select the image → open the Image Editor → crop/rotate → Save.
  • Repeat step 2 two or three more times.
  • View the image src (editor "Source" view or the saved field content): the query string accumulates — ???… — instead of being replaced.
  • (If assets are behind a CDN like CloudFront/Serverless Image Handler) the edited image also fails to display the change until multiple saves / a hard refresh, because the stale CDN copy keeps being served.

Additional info
Craft version: 5.10.5
PHP version: 8.2.28
Database driver & version: MySQL 8.0.40
Plugins & versions:
CKEditor (craftcms/ckeditor), 5.x branch (CKEditor 5, ckeditor5 ^48.2.0)
AWS S3 (craftcms/aws-s3) 2.3.0 — assets on S3 served via CloudFront + Serverless Image Handler

Activity

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

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions