Repository navigation
HEIC upload hangs indefinitely instead of falling back to server-side processing #81043
Description
Description
Uploading a HEIC file in the block editor causes the upload spinner to spin indefinitely and never complete. The original .heic file is saved to the uploads folder, but no resized sub-sizes (150/300/768/1024) are generated. No error appears in the browser console.
Step-by-step reproduction instructions
Steps to Reproduce
- Open the block editor and add an Image block (or use the Media Library uploader).
- Upload a .heic file.
- Observe the upload spinner.
Screenshots, screen recording, code snippet
Environment info
Environment
- WordPress: 7.1-beta4
- Subdirectory: No
- PHP: 8.4.23
- Server: PHP/8.4.23 (Development Server)
- Database: WP_SQLite_Driver (Server: 8.0.38 / Client: 3.53.2)
- Browser: Edge 150.0.0.0
- OS: Windows 11
- Theme: Twenty Twenty-Three 1.6
- MU Plugins:
- 99-studio-loader.php
- Plugins:
- Test Reports 1.3.0
- WordPress Beta Tester 4.0.0
- Note: Windows HEVC Video Extension (Microsoft Store) is not installed.
Expected Results
Per the "Client-Side Media Processing in WordPress 7.1" dev note, HEIC decoding depends on platform codecs and requires HEVC support on Windows. When the browser/OS cannot process the file client-side, WordPress should fall back to server-side processing automatically and transparently, with no visible change to the user.
Actual Results
The upload spinner keeps spinning and never completes. The original .heic file is written to the uploads folder, but no resized sub-sizes are generated. No error is shown in the browser console.
Additional Notes
- Test environment does not have the Windows HEVC Video Extension installed, which the dev note lists as a requirement for client-side HEIC decoding on Windows.
- Whether the lack of HEVC support is the actual trigger, or whether the fallback path itself is not being invoked, has not been confirmed.
- Reference: https://make.wordpress.org/core/2026/07/22/client-side-media-processing-in-wordpress-7-1/
Please confirm that you have searched existing issues in the repo.
- Yes
Please confirm that you have tested with all plugins deactivated except Gutenberg.
- Yes
Please confirm which theme type you used for testing.
- Block
- Classic
- Hybrid (e.g. classic with theme.json)
- Not sure
Metadata
Metadata
Assignees
Labels
Type
Projects
- StatusShow more project fields✅ Done
Activity
singhakanshu00 commentedon Aug 3, 2026
Root cause found — silent promise hang in strategy 2 of the HEIC client-side decoder
I traced this down to canvasConvertToJpeg() in packages/upload-media/src/canvas-utils.ts, which tries three decoding strategies in order:
Strategies 1 and 3 are both wrapped in try/catch, so a decode failure falls through cleanly to the next strategy. Strategy 2 was not (canvas-utils.ts:70-100 before this fix).
The failure mode: ImageDecoder.isTypeSupported(file.type) can optimistically return true based on container-format recognition alone, without confirming the platform actually has the underlying HEVC codec (exactly the Windows-without-HEVC-extension scenario in this report). When that mismatch happens, decoder.decode() doesn't reject — it just never settles. Since nothing throws, the try/finally around it never resolves either, the await canvasConvertToJpeg(...) call in private-actions.ts:886 (inside prepareItem()) hangs forever, and dispatch.cancelItem(...) is never reached. That matches the report exactly: spinner never resolves, original file already saved (it's written before this code path even queues the Upload operation), no console error (nothing ever throws or rejects).
Proposed fix
In canvas-utils.ts:
Net effect: on a platform where the codec claim is wrong, we now fail over to strategy 3 (or the final "browser can't decode HEIC" error) within ~8s instead of hanging indefinitely.
Open question before I put up a PR: is 8s a reasonable timeout value here, or is there a preferred constant/convention elsewhere in the codebase for this kind of guard?
Happy to open the PR once there's agreement on the approach.
t-hamano commentedon Aug 4, 2026
cc @adamsilverstein
adamsilverstein commentedon Aug 4, 2026
@singhakanshu00 thanks for the analysis. 8s feels like too much time to me if anything. I don't think we have an existing convention.
Yes, please work on a PR for this and we can ask @369work to test your fix.
@369work thanks so much for opening this bug report and testing this on your system. Some follow up questions:
369work commentedon Aug 5, 2026
Thanks for the follow-up questions, @adamsilverstein!
Site Health check:
Active editor is
WP_Image_Editor_GD. GD's supported file formats are GIF, JPEG, PNG, WebP, BMP, AVIF, XPM — HEIC/HEIF is not listed. So the server-side editor does not support HEIC, confirming your assumption. Screenshot attached below.HEVC Video Extension:
I checked the Microsoft Store, and only the paid version of the "HEVC Video Extensions from Device Manufacturer" is available for purchase on my device. Since this testing is volunteer work, I'm not planning to make the purchase. Is there an alternative way to verify the HEVC-dependent behavior without purchasing the paid version?
As a side note, uploading a ~1MB JPEG currently takes about 10 seconds on my setup, in case that's useful context for the timeout discussion.
singhakanshu00 commentedon Aug 5, 2026
PR is up: #81211
Fix:
one of the three client-side HEIC decode strategies in
canvas-utils.tswasn't wrapped intry/catchlike the other two. WhenImageDecoder.isTypeSupported()optimistically reports HEIC support without the actual codec present,decoder.decode()never settles instead of rejecting — hanging the upload forever with no error. Added a timeout that force-closes the decoder so it falls through to the next strategy (or a clean error) instead.On the timeout value: @369work's ~10s is total upload time (network + server processing), not decode time — a working decode finishes in well under a second, so per @adamsilverstein's feedback that 8s felt too long, I went with 3s: comfortably above realistic decode time, but short enough not to stall the user. Not derived from a formal benchmark, just a reasoned estimate — open to adjusting if there's better data.
Tested on Mac by simulating the exact "claims support, then hangs" condition via DevTools (no real Windows box without the HEVC extension available to me). Confirms the hang on
trunkand the fix recovering within ~3s, sub-sizes generating correctly.adamsilverstein commentedon Aug 5, 2026
Thanks for the additional details @369work and confirming the fix @singhakanshu00 .
Regarding installing the HEVC Video Extensions from Device Manufacturer extension, based on my reading of reddit threads, this is often installable for free or costs less than 1 $. Is that what you were seeing when you tried (I don't even see the install page on my mac).
@369work I understand not wanting to buy something for volunteer work, makes perfect sense! That said, I'd love to have real world confirmation from you that installing the extension fixes the uploader for you and would happily send you the $1 if that is indeed what it costs. Part of my time is sponsored (and part volunteer) so I am happy to pay for things like this.
7 remaining items
pbiron commentedon Aug 20, 2026
Reproduction Report
Environment
The above is a hand-rolled WAMP-like stack, with server and browser running on the same Win11 machine.
Initially I couldn't reproduce, the sample HEIC image was uploaded and sub-sizes were created (I haven't yet figured out how to tell whether the image was covered to JPG in the browser or on the server), but no hanging occurred. After adding an img block, I first tried clicking on the
Uploadbutton and selecting the .heic file on disk. That worked fine, no hanging. I then added another img block and clicked on theMedia Librarybutton and dragged-dropped the .heic file into the ML and that worked fine, no hanging.I do not have the
HEIC Video Extensioninstalled, but I do have Imagick, which understands HEICSo, I wrote a little one-line plugin to force use of GD and was then able to reproduce the hanging behavior when clicking the
Uploadbutton. When clicking theMedia Librarybutton and dragging-dropping an .heic file, there is no hanging but the img block shows a "broken image" icon:pbiron commentedon Aug 20, 2026
Note: after doing this testing, I think it'd be a good idea for the
Test Reportsplugin to also report which image editors are available. When I get a chance, I'll get with Andy and Colin and propose that to them.adamsilverstein commentedon Aug 23, 2026
Thanks for reproducing @pbiron - that sounds right, when you had Imagick as your default the system chose the server side path. Without it, you hit the bug.
Next, can you check if #81211 resolves the issue for you?
pbiron commentedon Aug 23, 2026
Yes, I will try later today.
369work commentedon Sep 4, 2026
Follow-up from my original report, with two new findings. Both came out of testing #82409, which had me try the Media Library modal upload path and re-check this on a machine with the codecs installed — neither of which I had covered when I first filed this.
1. The hang also happens with the codecs installed.
I originally suspected the missing Windows HEVC Video Extension was the trigger. I have since tested with both "HEIC Image Extensions" and "HEVC Video Extensions" installed, and the upload hangs in exactly the same way — the spinner never stops, the raw
.heicis saved towp-content/uploads, no sub-sizes are generated, and the Media Library shows a gray placeholder. Reproduced in Chrome 152 and Edge, and identically whether the file is dropped directly onto an Image block or onto the Media Library modal.So the stall does not appear to be limited to systems lacking OS-level codec support. It may be worth confirming that #81211 covers this case too.
2.
debug.logrecords PHP warnings that the browser console does not show.The console stays silent, but these are logged at the moment of upload:
These two warnings are the only entries logged for the upload — no fatal error. The server-side path does run, but it cannot read the HEIC dimensions, which matches the sub-sizes never being generated.
That raises a question about the fallback in #81211: once the client-side decode fails fast and hands off to server-side processing, does the server side actually generate usable sub-sizes for HEIC in this environment, or does it hit the same dimension-reading problem? Happy to test the patch if that would help.
Environment for this round of testing:
adamsilverstein commentedon Sep 5, 2026
Thanks for the additional testing @369work - does the fix in #81211 correct the issue for you even with the codec support installed??
369work commentedon Sep 5, 2026
Yes — #81211 fixes it for me, with the codecs installed.
Dropping a
.heicfile on an Image block now converts it to.jpgand renders it in the editor. The spinner runs briefly and completes instead of spinning forever. Same result in Chrome 152 and Edge.On the fallback question I raised earlier: my environment has no ImageMagick, so I expected an error rather than a conversion. It didn't need one — with the codecs installed, the conversion happens in the browser, so the server-side path is never reached.
The
image.phpwidth/heightwarnings I quoted in my earlier comment no longer appear indebug.logeither — it stays clean through both upload paths.If you drag it into a media modal, Media Library modal shows no spinner at all and ends silently, storing the
.heicunconverted — the block then shows a broken image.That is unchanged before and after this patch.
In the Media Library the two uploads sit side by side.
The one from the modal is a gray placeholder, the one dropped on the block has a working thumbnail.
When I returned to the site editor, an error was displayed.
'This image has an empty alt attribute;'
This is the behaviour described in #82409, which this PR doesn't touch, so I mention it only to be clear about the scope of my test.
Environment
Media: Fall through only when the ImageDecoder decode times out