{"record":{"id":"a6ac9b261d1871f3","repo":"wailsapp/wails","slug":"createstreamonhglobal-failed-with-e-invalidarg","errorCode":null,"errorMessage":"CreateStreamOnHGlobal failed with E_INVALIDARG","messagePattern":"CreateStreamOnHGlobal failed with E_INVALIDARG","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"v3/pkg/w32/ole32.go","lineNumber":83,"sourceCode":"\tcase E_OUTOFMEMORY:\n\t\tpanic(\"CoCreateInstance failed with E_OUTOFMEMORY\")\n\tcase E_UNEXPECTED:\n\t\tpanic(\"CoCreateInstance failed with E_UNEXPECTED\")\n\t}\n\n\treturn HRESULT(ret)\n}\n\nfunc CreateStreamOnHGlobal(hGlobal HGLOBAL, fDeleteOnRelease bool) *IStream {\n\tstream := new(IStream)\n\tret, _, _ := procCreateStreamOnHGlobal.Call(\n\t\tuintptr(hGlobal),\n\t\tuintptr(BoolToBOOL(fDeleteOnRelease)),\n\t\tuintptr(unsafe.Pointer(&stream)))\n\n\tswitch uint32(ret) {\n\tcase E_INVALIDARG:\n\t\tpanic(\"CreateStreamOnHGlobal failed with E_INVALIDARG\")\n\tcase E_OUTOFMEMORY:\n\t\tpanic(\"CreateStreamOnHGlobal failed with E_OUTOFMEMORY\")\n\tcase E_UNEXPECTED:\n\t\tpanic(\"CreateStreamOnHGlobal failed with E_UNEXPECTED\")\n\t}\n\n\treturn stream\n}\nfunc OleInitialise() {\n\tprocOleInitialize.Call()\n}\n\nfunc RegisterDragDrop(hwnd HWND, dropTarget *DropTarget) error {\n\n\tdt := combridge.New[iDropTarget](dropTarget)\n\thr, _, _ := procRegisterDragDrop.Call(\n\t\thwnd,\n\t\tdt.Ref(),","sourceCodeStart":65,"sourceCodeEnd":101,"githubUrl":"https://github.com/wailsapp/wails/blob/0e754b1b40ba9044c2a1460e23b7c3de20fc5cf3/v3/pkg/w32/ole32.go#L65-L101","documentation":"The Go wrapper around the Win32 CreateStreamOnHGlobal API panicked because the call returned E_INVALIDARG. This API creates an IStream over a global-memory block (HGLOBAL); E_INVALIDARG means the arguments were rejected, almost always because hGlobal is 0, was not allocated by GlobalAlloc, or the out-pointer for the stream was invalid. The wrapper converts the HRESULT into a Go panic instead of returning an error.","triggerScenarios":"Calling w32.CreateStreamOnHGlobal with a nil/zero HGLOBAL (e.g. a failed GlobalAlloc whose error was ignored), passing a handle from a different allocator (LocalAlloc/heap), or calling after the HGLOBAL was already freed with GlobalFree.","commonSituations":"Clipboard (SetClipboardData) and drag-and-drop (DROPDESCRIPTION / SHDoDragDrop) helper code that builds an IStream from an HGLOBAL without checking GlobalAlloc's return; freeing the HGLOBAL before the stream is released; double-create on the same handle with fDeleteOnRelease=true.","solutions":["Check the HGLOBAL is non-zero immediately after GlobalAlloc and before calling CreateStreamOnHGlobal","Ensure the buffer was allocated with GlobalAlloc(GMEM_MOVEABLE|GMEM_SHARE,...) — streams require a movable allocation, not GMEM_FIXED in some paths","Do not GlobalFree the handle yourself when fDeleteOnRelease=true; let the stream own it","Wrap the call in a recover() to turn the panic into an error if you cannot fully validate the handle"],"exampleFix":"// before\nh := GlobalAlloc(GMEM_MOVEABLE, size)\nstream := w32.CreateStreamOnHGlobal(h, true) // panics if h == 0\n\n// after\nh := GlobalAlloc(GMEM_MOVEABLE, size)\nif h == 0 {\n    return fmt.Errorf(\"GlobalAlloc failed: %w\", errno.ERROR_NOT_ENOUGH_MEMORY)\n}\nstream := w32.CreateStreamOnHGlobal(h, true)","handlingStrategy":"validation","validationCode":"if hGlobal == 0 {\n    return fmt.Errorf(\"invalid HGLOBAL (0); GlobalAlloc probably failed\")\n}\nstream := w32.CreateStreamOnHGlobal(hGlobal, true)","typeGuard":null,"tryCatchPattern":"defer func() {\n    if r := recover(); r != nil {\n        return fmt.Errorf(\"CreateStreamOnHGlobal failed: %v\", r)\n    }\n}()\nstream := w32.CreateStreamOnHGlobal(h, true)","preventionTips":["Always check GlobalAlloc's return before building a stream on it","Allocate with GMEM_MOVEABLE; let fDeleteOnRelease own the free","Never reuse an HGLOBAL after its stream was released"],"tags":["windows","win32","ole","memory","panic"],"backgroundTag":null,"analyzedSha":"0e754b1b40ba9044c2a1460e23b7c3de20fc5cf3","analyzedAt":"2026-08-15T14:17:36.034Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}