{"record":{"id":"927df7dbd41fdbfb","repo":"memstechtips/Winhance","slug":"dism-operation-timed-out-after-hardtimeoutseconds","errorCode":null,"errorMessage":"DISM operation timed out after {HardTimeoutSeconds}s","messagePattern":"DISM operation timed out after (.+?)s","errorType":"exception","errorClass":"OperationCanceledException","httpStatus":null,"severity":"critical","filePath":"src/Winhance.Infrastructure/Features/Common/Utilities/DismSessionManager.cs","lineNumber":77,"sourceCode":"                        log?.Invoke(\"[DismSession] Calling DismCloseSession...\");\r\n                        DismApi.DismCloseSession(session);\r\n                        log?.Invoke(\"[DismSession] DismCloseSession done\");\r\n                    }\r\n                }\r\n                finally\r\n                {\r\n                    log?.Invoke(\"[DismSession] Calling DismShutdown...\");\r\n                    DismApi.DismShutdown();\r\n                    log?.Invoke(\"[DismSession] DismShutdown done\");\r\n                }\r\n            }, ct);\r\n\r\n            var timeoutTask = Task.Delay(TimeSpan.FromSeconds(HardTimeoutSeconds), ct);\r\n\r\n            if (await Task.WhenAny(workTask, timeoutTask).ConfigureAwait(false) == timeoutTask)\r\n            {\r\n                log?.Invoke($\"[DismSession] HARD TIMEOUT after {HardTimeoutSeconds}s — native DISM call is unresponsive, abandoning thread\");\r\n                throw new OperationCanceledException($\"DISM operation timed out after {HardTimeoutSeconds}s\");\r\n            }\r\n\r\n            return await workTask.ConfigureAwait(false);\r\n        }\r\n        catch (OperationCanceledException)\r\n        {\r\n            log?.Invoke($\"[DismSession] Operation cancelled/timed out in ExecuteAsync<T>\");\r\n            throw;\r\n        }\r\n        catch (Exception ex)\r\n        {\r\n            log?.Invoke($\"[DismSession] EXCEPTION in ExecuteAsync<T>: {ex.GetType().Name}: {ex.Message}\");\r\n            throw;\r\n        }\r\n        finally\r\n        {\r\n            _lock.Release();\r\n            log?.Invoke($\"[DismSession] Semaphore released. Total elapsed={sw.ElapsedMilliseconds}ms\");\r","sourceCodeStart":59,"sourceCodeEnd":95,"githubUrl":"https://github.com/memstechtips/Winhance/blob/f23d554eb2d6400b1827bcc46b91294ffa53fbc9/src/Winhance.Infrastructure/Features/Common/Utilities/DismSessionManager.cs#L59-L95","documentation":"OperationCanceledException thrown by DismSessionManager.ExecuteAsync<T> when a native DISM call (run on a pooled thread under a single-semaphore lock) does not complete within the 30-second HardTimeoutSeconds deadline. Native DISM cannot be cancelled via CancellationToken, so Task.WhenAny races the work task against a 30s delay; if the delay wins, the thread is abandoned and the exception thrown to abort the caller.","triggerScenarios":"ExecuteAsync<T> acquires the global DISM semaphore, Task.Run's the native call (DismInitialize + the action + DismShutdown), and Task.WhenAny returns the timeoutTask first. Happens when DISM hangs on a corrupt image, a network-backed source, a locked file, or a servicing stack in a bad state. Also if the system is under heavy I/O and DISM is slow to respond.","commonSituations":"The WIM/image path is on a slow network share. The image is corrupted and DISM loops internally. Another DISM process holds resources. The 30s budget is too short for a large image on a slow machine. Antivirus is scanning the image and slowing DISM I/O.","solutions":["Retry once after a reboot — a transient DISM hang often clears when the servicing stack resets.","Move the image to a local fast drive (avoid network/USB sources) and retry.","Run `DISM /Online /Cleanup-Image /RestoreHealth` and `sfc /scannow` to repair a corrupt servicing stack, then retry.","If the image is large and the 30s deadline is genuinely too short on this hardware, raise HardTimeoutSeconds (note: it is a const — make it configurable).","Ensure no antivirus is scanning the image during the DISM call (add an exclusion)."],"exampleFix":"// before: hard-coded 30s, thread abandoned on timeout\nprivate const int HardTimeoutSeconds = 30;\nif (await Task.WhenAny(workTask, timeoutTask).ConfigureAwait(false) == timeoutTask)\n    throw new OperationCanceledException($\"DISM operation timed out after {HardTimeoutSeconds}s\");\n\n// after: configurable timeout, longer for known-slow operations\nprivate static int HardTimeoutSeconds => AppContext.GetData(\"DISM_HARD_TIMEOUT\") is string s && int.TryParse(s, out var v) ? v : 60;\nif (await Task.WhenAny(workTask, timeoutTask).ConfigureAwait(false) == timeoutTask)\n    throw new OperationCanceledException($\"DISM operation timed out after {HardTimeoutSeconds}s. The image may be corrupt or on slow storage.\");","handlingStrategy":"retry","validationCode":"// Pre-flight: ensure the image is local and the servicing stack is healthy.\nbool IsHealthyForNativeDism(string imagePath) =>\n    _fileSystemService.FileExists(imagePath) && !imagePath.StartsWith(@\"\\\\\");","typeGuard":null,"tryCatchPattern":"catch (OperationCanceledException ex) when (ex.Message.Contains(\"DISM operation timed out\"))\n{\n    // After a hard timeout the DISM engine may be wedged; advise a reboot before any retry.\n    // Do NOT immediately retry on the same image — that re-wedges the same pooled thread.\n}","preventionTips":["Keep images on local fast storage for native DISM calls.","Exclude the image/working folder from antivirus scans.","Repair the servicing stack periodically (sfc + DISM /RestoreHealth).","Make HardTimeoutSeconds configurable for slow hardware/large images."],"tags":["dism","native","timeout","interop","threading","windows"],"backgroundTag":null,"analyzedSha":"f23d554eb2d6400b1827bcc46b91294ffa53fbc9","analyzedAt":"2026-08-13T17:55:20.922Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}