Problem/Motivation
Drupal provides a mechanism to periodically clean up cached external images — removing both derivative (styled) and original versions to free up disk space.
This is useful to avoid accumulating unused image files.
However, when full-page caching or external page caches (e.g., Varnish, CDN, or Drupal’s internal page cache) are in use, a problem occurs:
The original image from the external source is downloaded and cached when the content is first rendered.
Later, if the cached originals and derivatives are deleted by the cleanup process, and the HTML page remains served from cache, users will still request image style URLs that no longer exist.
When Drupal receives the request for the missing image style, it attempts to regenerate it using the original file — but since the original has been deleted, this regeneration fails.
The missing original will only be recreated once Drupal re-renders the content (i.e., when the page cache is invalidated). Until then, the images remain broken.
This leads to broken image derivatives on cached pages when original cached external images are removed prematurely.
Steps to reproduce
- Enable image styles that use external image sources (e.g., via imagecache_external or similar system).
- Enable page caching (Drupal internal cache or reverse proxy).
- Visit a page containing external images styled by Drupal (e.g., using an image style).
- The original image and its derivatives are now cached locally.
- Run the image cleanup process that deletes cached originals and derivatives.
- Request the same page again (still served from cache).
Result:
- The HTML references cached image style URLs that no longer exist.
- Drupal cannot regenerate derivatives because the original file is missing.
- Images appear broken until the cache entry is invalidated and content is re-rendered.
Proposed resolution
Add a configuration option to the image cleanup process (or the relevant service/module) allowing administrators to exclude original cached external images from deletion while still removing derivative images.
Possible technical solutions:
- Introduce a new configuration key in the cleanup service (e.g., delete_originals = TRUE/FALSE).
- Modify the cleanup cron logic to check this setting before deleting original files.
- Optionally, expose this setting in the UI under the image toolkit or file system configuration page.
- Extend documentation to clarify how page caching interacts with image cache cleanup and potential side effects.
Benefits:
- Prevents broken images on cached pages.
- Maintains disk space optimization for derived images.
- Provides better control to site administrators over cleanup behavior.
Remaining tasks
- Identify the service or cron task responsible for cleaning cached images (e.g., image_cron() or module-specific cleanup function).
- Add configuration schema and default value for the new setting.
- Implement logic to skip deletion of original cached external images when the setting is enabled.
User interface changes
- Add a checkbox under image cache or file system cleanup settings:
- “Exclude original external images from cleanup (only remove derived image styles)”
- Default: unchecked (maintains current behavior).
Issue fork imagecache_external-3552589
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #3
lpeidro commentedComment #4
lpeidro commentedReady for testing.
Comment #5
swentel commentedThat looks pretty cool! I'll review this over the weekend together with another feature request!
Comment #6
swentel commentedMerge 3.0.x + two changes:
- added an update hook to set imagecache_external_cron_flush_originals to TRUE ($config->get() doesn't have a default value param)
- removed the visibility state depending on cron flush - because you can also flush manually, you really want to know about this setting :)
Comment #7
swentel commentedAdded a test as well, ready to merge.
Comment #9
swentel commentedmerged, thanks!
Comment #11
swentel commented