Description
Description
When using client-side media handling (the "Client Side Media" experiment), uploading a large image that exceeds the big_image_size_threshold (default 2560px) correctly creates and uploads a -scaled version, but does not upload the original full-size image to the server.
This differs from server-side WordPress behavior, where both the original file and the -scaled file exist on disk after upload.
Expected behavior
When a large image (e.g., 4000x3000) is uploaded with client-side media enabled:
- The
-scaled version should be uploaded as the main attachment (this works correctly today)
- The original full-size image should also be uploaded/sideloaded to the server
- The attachment metadata should include
original_image pointing to the original file on disk
This matches WordPress core's server-side behavior in wp_create_image_subsizes(), where both files are retained on the server.
Current behavior
Only the -scaled version is uploaded to the server. The original image is kept in browser memory (as item.sourceFile) and used for thumbnail generation, but is never sent to the server. As a result:
- The original file does not exist on the server filesystem
- The
original_image metadata may be missing or incorrect
- Plugins and features that depend on the original file being present (e.g., "Edit Original Image", thumbnail regeneration plugins) will not work as expected
Screenshots
Server-side handling (both original and scaled exist on disk):

Client-side media handling (only scaled exists):

Note: the generated sub-sizes match correctly between both approaches.
Technical details
In packages/upload-media/src/store/private-actions.ts, the prepareItem action queues a ResizeCrop operation with isThresholdResize: true followed by an Upload. The resize creates the -scaled file in resizeCropItem, which replaces item.file. The subsequent upload sends only this scaled file.
The original image is preserved in item.sourceFile and is used as the source for thumbnail generation in generateThumbnails, but it is never sideloaded to the server as a separate file.
Proposed fix
After the initial -scaled upload completes, sideload the original full-size image to the server with image_size: 'original'. The sideload endpoint (class-gutenberg-rest-attachments-controller.php) already handles this case and stores the reference in metadata['original_image']:
if ( 'original' === $image_size ) {
$metadata['original_image'] = wp_basename( $path );
}
The fix would add a sideload step in generateThumbnails (or uploadItem) for the original sourceFile when the image was threshold-scaled, similar to how the -rotated version is already sideloaded for images needing EXIF rotation.
Related
Step-by-step reproduction instructions
- Enable Gutenberg > Experiments > Client Side Media
- Upload an image larger than 2560px in either dimension (alternately use the
big_image_size_threshold filter to use smaller images)
- Check the uploads directory on the server — only the
-scaled file is present; the original is missing
- Compare with the same upload when the experiment is disabled — both the original and
-scaled files are present
Screenshots, screen recording, code snippet
No response
Environment info
No response
Please confirm that you have searched existing issues in the repo.
Please confirm that you have tested with all plugins deactivated except Gutenberg.
Please confirm which theme type you used for testing.
Description
Description
When using client-side media handling (the "Client Side Media" experiment), uploading a large image that exceeds the
big_image_size_threshold(default 2560px) correctly creates and uploads a-scaledversion, but does not upload the original full-size image to the server.This differs from server-side WordPress behavior, where both the original file and the
-scaledfile exist on disk after upload.Expected behavior
When a large image (e.g., 4000x3000) is uploaded with client-side media enabled:
-scaledversion should be uploaded as the main attachment (this works correctly today)original_imagepointing to the original file on diskThis matches WordPress core's server-side behavior in
wp_create_image_subsizes(), where both files are retained on the server.Current behavior
Only the
-scaledversion is uploaded to the server. The original image is kept in browser memory (asitem.sourceFile) and used for thumbnail generation, but is never sent to the server. As a result:original_imagemetadata may be missing or incorrectScreenshots
Server-side handling (both original and scaled exist on disk):

Client-side media handling (only scaled exists):

Note: the generated sub-sizes match correctly between both approaches.
Technical details
In
packages/upload-media/src/store/private-actions.ts, theprepareItemaction queues aResizeCropoperation withisThresholdResize: truefollowed by anUpload. The resize creates the-scaledfile inresizeCropItem, which replacesitem.file. The subsequent upload sends only this scaled file.The original image is preserved in
item.sourceFileand is used as the source for thumbnail generation ingenerateThumbnails, but it is never sideloaded to the server as a separate file.Proposed fix
After the initial
-scaledupload completes, sideload the original full-size image to the server withimage_size: 'original'. The sideload endpoint (class-gutenberg-rest-attachments-controller.php) already handles this case and stores the reference inmetadata['original_image']:The fix would add a sideload step in
generateThumbnails(oruploadItem) for the originalsourceFilewhen the image was threshold-scaled, similar to how the-rotatedversion is already sideloaded for images needing EXIF rotation.Related
Step-by-step reproduction instructions
big_image_size_thresholdfilter to use smaller images)-scaledfile is present; the original is missing-scaledfiles are presentScreenshots, screen recording, code snippet
No response
Environment info
No response
Please confirm that you have searched existing issues in the repo.
Please confirm that you have tested with all plugins deactivated except Gutenberg.
Please confirm which theme type you used for testing.