{"record":{"id":"ef385bb76694668e","repo":"dotnet/wpf","slug":"win32exception-native-win32-error-from-duplicatehandle","errorCode":null,"errorMessage":"Win32Exception (native Win32 error from DuplicateHandle failure)","messagePattern":"Win32Exception \\(native Win32 error from DuplicateHandle failure\\)","errorType":"exception","errorClass":"Win32Exception","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/Imaging/WriteableBitmap.cs","lineNumber":1303,"sourceCode":"            // We are going to pass an event in the command packet we send to\n            // the composition thread.  We need to make sure the event stays \n            // alive in case we get collected before the composition thread\n            // processes the packet.  We do this by duplicating the event\n            // handle, and the composition thread will close the handle after\n            // signalling it.\n            IntPtr hDuplicate;\n            IntPtr hCurrentProc = MS.Win32.UnsafeNativeMethods.GetCurrentProcess();\n            if (!MS.Win32.UnsafeNativeMethods.DuplicateHandle(\n                    hCurrentProc,\n                    _copyCompletedEvent.SafeWaitHandle,\n                    hCurrentProc,\n                    out hDuplicate,\n                    0,\n                    false,\n                    MS.Win32.UnsafeNativeMethods.DUPLICATE_SAME_ACCESS\n                    ))\n            {\n                throw new Win32Exception();\n            }\n\n            DUCE.MILCMD_DOUBLEBUFFEREDBITMAP_COPYFORWARD command;\n            command.Type = MILCMD.MilCmdDoubleBufferedBitmapCopyForward;\n            command.Handle = _duceResource.GetHandle(channel);\n            command.CopyCompletedEvent = (UInt64) hDuplicate.ToInt64();\n\n            // Note that the batch is closed after the sendcommand because this method is called under the \n            // context of the MediaContext.CommitChannel and the command needs to make it into the current set of changes which are \n            // being commited to the compositor.  If the batch is not closed, it would go into the \n            // \"future\" batch which would not get submitted this time around. This leads to a dead-lock situation which occurs when \n            // the app calls Lock on the WriteableBitmap because Lock waits on _copyCompletedEvent which the compositor sets when it sees the \n            // Present command. However, since the compositor does not get the Present command, it will not set the event and the \n            // UI thread will wait forever on the compositor which will cause the application to stop responding.\n            // Another option is to send the command in its own batch (instead of closing the batch). This doesn't work in all cases \n            // because the command for creating the resource handle (AddRefOnChannelCore) or the command for initializing the resource (UpdateBitmapSourceResource)\n            // could be in the \"future\" batch thus crashing the CopyForward operation in this batch.\n","sourceCodeStart":1285,"sourceCodeEnd":1321,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/Imaging/WriteableBitmap.cs#L1285-L1321","documentation":"In OnCommittingBatch, WriteableBitmap duplicates an event-handle via Win32 DuplicateHandle to signal copy-forward completion on the render thread. If DuplicateHandle fails (returns FALSE), the code throws Win32Exception carrying the native Win32 error code, meaning the handle duplication into the render process failed.","triggerScenarios":"Committing a WriteableBitmap render batch when DuplicateHandle fails — typically due to handle exhaustion, insufficient access rights on the source handle, or an invalid/closed source process handle.","commonSituations":"Systems with handle leaks/exhaustion (thousands of GDI/kernel handles), running under restricted jobs or AppContainer sandboxes that limit handle duplication, or heavy WriteableBitmap churn causing race conditions on teardown.","solutions":["Check the Win32Exception.NativeErrorCode; if ERROR_NO_SYSTEM_RESOURCES/handle exhaustion, audit and fix handle leaks in the app (use Process Explorer to count handles).","Ensure the WriteableBitmap and its host (e.g., Image) are not used after disposal/window close; re-create the bitmap if the previous one was torn down.","Retry the operation; if transient under low-memory conditions, reduce simultaneous bitmap allocations.","If it reproduces consistently under a sandbox/job object, grant the process rights to duplicate handles or run outside the restriction."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Check handle pressure before heavy bitmap work:\nusing var p = Process.GetCurrentProcess();\nif (p.HandleCount > 10000) { /* fix leaks before creating more bitmap batches */ }","typeGuard":null,"tryCatchPattern":"try { bitmap.WritePixels(rect, buffer, stride, 0); }\ncatch (Win32Exception ex) { Log(ex.NativeErrorCode); if (IsHandleExhaustion(ex.NativeErrorCode)) ReduceHandleUsage(); else throw; }","preventionTips":["Audit and dispose GDI/kernel handles; monitor HandleCount in production","Keep WriteableBitmap instances alive while in use; avoid use-after-dispose","Test the app under job-object/sandbox restrictions if you deploy in AppContainer environments"],"tags":["wpf","win32","handle","duplicatehandle","render-thread"],"backgroundTag":"win32-handle-duplication-failed","analyzedSha":"81131a70a4c573cd62748a5c36908fc4d662daa9","analyzedAt":"2026-09-14T10:12:48.479Z","contentChangedAt":"2026-09-14T10:12:48.479Z","schemaVersion":2},"datasetVersion":"2026-09-21T21:30:21.729Z"}