- WDD Version: 5.7.0
- OS Version: Windows 11 Pro 26220
Steps to Reproduce:
- Build a theme whose
imageFilename points at images in a format GDI+ cannot decode — .webp is the easy case — and package it as a .ddw.
- Theme dialog -> Import from file -> pick it. The import itself succeeds and the progress bar reaches 100%.
- The dialog switches to "Generating thumbnails, please wait..." and stays there forever. No error is shown, nothing is written to the log, and the theme dialog stays disabled behind it, so the app has to be killed from Task Manager.
Are you using the Microsoft Store version of WDD?: No. Problem initially seen in installer version (from releases), then to verify I built from source at 965e009. Same issue.
Cause
ThemeThumbLoader.GetThumbnailImage decodes with System.Drawing, and GDI+ throws for formats it cannot read. On a .webp file Image.FromFile throws ExternalException ("An object could not be created, possibly due to a lack of memory, but most likely due to invalid input"), which I confirmed directly against this code.
ThemeDialogUtils.LoadThemes only catches OutOfMemoryException, so that exception escapes the loop. Because LoadImportedThemes runs LoadThemes on a Task and closes the dialog on the line after it, the task faults, thumbnailsLoaded is never set, importDialog.Close() is never reached, and OnImportDialogClosing keeps cancelling the close. Nothing is logged because the faulted task is never observed.
Two side effects of the same escape:
loadSemaphore is acquired at the top of LoadThemes and released on its last line, so the release is skipped and the next load blocks for the full 60s timeout.
- The failure is completely silent — no dialog, no
debug.log entry, even with debug logging enabled.
This is not WebP-specific. Any image GDI+ refuses — a truncated JPEG, a .heic that slipped through — produces the same indefinite hang.
Why it can look intermittent
A cached thumbnail is only reused when its size matches the request exactly (GetThumbnailImage). So:
- A theme shipping a 192x108
thumbnail.png imports fine at 100% scaling — the cached file is returned before any theme image is touched.
- The same theme with a differently sized
thumbnail.png, or that same 192x108 file on a 150% display where the requested size becomes 256x144, falls through to regenerating from the theme images, and hangs.
That also means bundled thumbnails are discarded and regenerated on every load on any display that is not at 100% scaling, which is wasted work independent of this bug.
Fix
I have a PR ready that keeps this scoped to robustness — broaden the catch and log the exception, release the semaphore from a finally, and close the import dialog from a finally so the import always completes. It makes the failure visible and recoverable without changing which formats are supported.
Separately, and related to #690: the 5.7.0 Skia preview renderer already decodes WebP through SKCodec in Skia/ImageCache.cs, so preview works while thumbnail generation does not. Routing thumbnail decoding through SKCodec as well makes WebP work end to end. I have that as a second PR if you want it — happy to send only the hang fix if you would rather keep thumbnail decoding on System.Drawing.
Steps to Reproduce:
imageFilenamepoints at images in a format GDI+ cannot decode —.webpis the easy case — and package it as a.ddw.Are you using the Microsoft Store version of WDD?: No. Problem initially seen in installer version (from releases), then to verify I built from source at 965e009. Same issue.
Cause
ThemeThumbLoader.GetThumbnailImagedecodes withSystem.Drawing, and GDI+ throws for formats it cannot read. On a.webpfileImage.FromFilethrowsExternalException("An object could not be created, possibly due to a lack of memory, but most likely due to invalid input"), which I confirmed directly against this code.ThemeDialogUtils.LoadThemesonly catchesOutOfMemoryException, so that exception escapes the loop. BecauseLoadImportedThemesrunsLoadThemeson aTaskand closes the dialog on the line after it, the task faults,thumbnailsLoadedis never set,importDialog.Close()is never reached, andOnImportDialogClosingkeeps cancelling the close. Nothing is logged because the faulted task is never observed.Two side effects of the same escape:
loadSemaphoreis acquired at the top ofLoadThemesand released on its last line, so the release is skipped and the next load blocks for the full 60s timeout.debug.logentry, even with debug logging enabled.This is not WebP-specific. Any image GDI+ refuses — a truncated JPEG, a
.heicthat slipped through — produces the same indefinite hang.Why it can look intermittent
A cached thumbnail is only reused when its size matches the request exactly (
GetThumbnailImage). So:thumbnail.pngimports fine at 100% scaling — the cached file is returned before any theme image is touched.thumbnail.png, or that same 192x108 file on a 150% display where the requested size becomes 256x144, falls through to regenerating from the theme images, and hangs.That also means bundled thumbnails are discarded and regenerated on every load on any display that is not at 100% scaling, which is wasted work independent of this bug.
Fix
I have a PR ready that keeps this scoped to robustness — broaden the catch and log the exception, release the semaphore from a
finally, and close the import dialog from afinallyso the import always completes. It makes the failure visible and recoverable without changing which formats are supported.Separately, and related to #690: the 5.7.0 Skia preview renderer already decodes WebP through
SKCodecinSkia/ImageCache.cs, so preview works while thumbnail generation does not. Routing thumbnail decoding throughSKCodecas well makes WebP work end to end. I have that as a second PR if you want it — happy to send only the hang fix if you would rather keep thumbnail decoding onSystem.Drawing.