[5.x]: Asset Transforms Are Not Removed When An Asset is Replaced
What happened?
Description
We replaced an image asset using the asset manager but all entries that use the asset are still displaying the old image. This is because Craft is not deleting old images transforms. I've tried all cache clearing mechanisms and Craft will not delete old image transforms. Only manual deletion is successful.
Steps to reproduce
- Add an image asset to a matrix
- Create an entry using the matrix
- Use twig function tag to create an image tag and pass a transform via twig as well
- Upload an image
- Replace the previous image with a new image through the asset manager
Expected behavior
Craft should be deleting old images transforms when an asset is replaced, or when template caches are cleared
Actual behavior
The old image persists
Craft CMS version
5.3.6
PHP version
8.2
Operating system and version
No response
Database type and version
No response
Image driver and version
No response
Installed plugins and versions
Hi, thanks for getting in touch! Let me check if I understand this correctly,
- you have an entry with a matrix field with an assets field;
- you upload an image to that assets field;
- you view the entry on the front end and see the image you uploaded, transformed as per the transform you used
- you the go to control panel > Assets and replace the file for that asset with a new one
- you view the entry on the front end, and you see the old file, not the new one
Is that correct?
Could you please share a snippet of your twig code? Are you using a named transform (defined in the control panel), or are you defining one in your template?
Hi, thanks for the response. This is our image twig component:
{% if image is defined and image|length %}
{% if imageAltTag is defined and imageAltTag|length %}
{% set altTag = imageAltTag %}
{% else %}
{% set altTag = '#REDACTED#' %}
{% endif %}
<div{% if extraClasses is defined %} class="{{ extraClasses }}"{% endif %}>
{{ tag('img', {
class: imageClasses,
srcset: image.one.setTransform({width: width, height: height, format: 'webp', quality: 80, mode: mode}).getSrcset(['1.5x']),
src: image.one.setTransform({ width: width, height: height, format: 'webp', quality: 80, mode: mode}),
width: width,
height: height,
alt: altTag,
}) }}
</div>
{% endif %}
The problem isn't with the generation of the images, it's that the transforms are not being cleaned up when the image is replaced, or when any of the caches are cleared.
Many thanks!
Additionally, we are using some cache tags throughout our templates, however considering that I am clearing the caches to solve the issue (with no effect), I wouldn't have though these would have any bearing on transforms not being cleaned up?
Thanks! What filesystem are you using for your transforms (aws s3, local, etc)? Are you using CDN to serve the transformed images?
I am seeing this same behavior in Craft 5.5.7 with my assets stored in S3 (fronted by Cloudflare). I am using the "Replace file" option on the asset page, but Craft never clears the stored transforms in the S3 bucket and continues showing the old image on the front-end. If I manually delete the asset's rows from the imagetransforindex table, then it does regenerate them from the new image, but I can't find any way to trigger this behavior through the interface.
Craft keeps track of when transforms were generated, and will return a new transform generation URL even if the file already exists, if the record of the transform is older than the asset’s dateModified value (which gets updated when you select “Replace file”.
Just tested locally and it’s working as expected. After replacing a file, pages are getting transform generation URLs that result in an updated transform image, even if the previous transform file still exists.
Not sure why it wouldn’t be working in your cases, but the first thing I’d probably check is to make sure all servers’ system clocks are set correctly.