Make WordPress Core

Opened 2 days ago

Last modified 34 hours ago

#65708 new defect (bug)

Media: HEIC to JPG conversion can create an orphaned full size JPG file and incorrectly versioned files

Reported by: ianmjones Owned by:
Priority: normal Milestone: Awaiting Review
Component: Media Version:
Severity: normal Keywords: has-patch has-unit-tests
Cc: Focuses:

Description

When adding a large HEIC image to an Image block, the client side conversion can result in a "-scaled.jpg" file as the "original_image", but also "-scaled-1.jpg" as the "file", along with the thumbnails all having the "-1" suffix.

Along with this, a JPG with the same base file name as the HEIC is created, but not added to the "_wp_attachment_metadata" options record, meaning it is effectively orphaned.

When you "Delete Permanently" the Media Library item, the JPG without "-scaled" is left on the server.

This can be demonstrated by adding the "shelf-christmas-decoration.heic" image from https://heic.digital/samples/ to an Image block.

I'll attached some screenshots that show the metadata, generated files, and orphaned file after delete of the Media Library item.

Attachments (3)

attachment-metadata.png (288.7 KB ) - added by ianmjones 2 days ago.
attachments-files-on-disk.png (284.4 KB ) - added by ianmjones 2 days ago.
orphaned-file-after-media-library-item-deleted.png (60.2 KB ) - added by ianmjones 2 days ago.

Download all attachments as: .zip

Change History (5)

#1 @ianmjones
2 days ago

I'm guessing that what should happen for this example, is ...

  • shelf-christmas-decoration.heic converted to shelf-christmas-decoration.jpg
  • shelf-christmas-decoration.jpg scaled to shelf-christmas-decoration-scaled.jpg
  • Thumbnails generated with shelf-christmas-decoration-WxH.jpg name format.

Giving ...

source_image: shelf-christmas-decoration.heic
original_image: shelf-christmas-decoration.jpg
file: 2026/07/shelf-christmas-decoration-scaled.jpg
thumbnail: shelf-christmas-decoration-150x150.jpg

Etc.

This ticket was mentioned in PR #12689 on WordPress/wordpress-develop by @khokansardar.


34 hours ago
#2

  • Keywords has-patch has-unit-tests added

When an attachment is uploaded with generate_sub_sizes set to false, the client generates all derivatives itself — including the scaled full-size image it later supplies through the sideload endpoint. create_item() already suppressed thumbnail generation and EXIF rotation in this case, but not the "big image" downscaling gated by the big_image_size_threshold filter.

What the problem was:

  • A large client-converted image (e.g. a HEIC converted to JPEG in the browser) was still scaled server-side to a -scaled file, which became the attached file while the untouched upload was recorded as original_image.
  • The client's subsequent scaled sideload then collided with that -scaled file and was renamed -scaled-1; the thumbnails inherited the numbered name.
  • The server-generated full-size file was left orphaned on disk and remained after the Media Library item was permanently deleted.

What the fix does:

  • Disables big_image_size_threshold alongside the existing client-side processing filters in create_item(), and removes it again in remove_client_side_media_processing_filters().
  • The uploaded full-size image is stored untouched, so the client's scaled sideload records it as original_image and keeps the plain -scaled name.

Approach and why:

  • generate_sub_sizes = false is the contract that the client owns all derivative generation, which includes the scaled full-size image. Server-side scaling in that mode duplicates the client's work and causes the collision. Suppressing it is the minimal, consistent change — it sits directly beside the three filters already applied for the same purpose.

Trac ticket: https://core.trac.wordpress.org/ticket/65708

## Use of AI Tools

AI assistance: Yes
Tool(s): Claude Code
Model(s): Claude Opus 4.8
Used for: Ticket analysis, code implementation, and tests. All changes were reviewed and validated by me.

Note: See TracTickets for help on using tickets.