Flow-Launcher/Flow.Launcher · error · Exception
SHBindToParent failed
Error message
SHBindToParent failed
What it means
Thrown when shell32!SHBindToParent returns a non-zero HRESULT after a PIDL has been successfully parsed by SHParseDisplayName. SHBindToParent walks the PIDL to its last item and returns an IShellFolder pointer for the parent plus a child-only PIDL; failure here means the binding chain to the parent folder broke even though the item name parsed. As with error 20 the HRESULT is discarded. This call sits between parsing the PIDL and asking the parent folder for an IContextMenu.
Source
Thrown at Plugins/Flow.Launcher.Plugin.Explorer/Helper/ShellContextMenuDisplayHelper.cs:192
IMalloc malloc = null;
IntPtr originalPidl = IntPtr.Zero;
IntPtr pShellFolder = IntPtr.Zero;
IntPtr pContextMenu = IntPtr.Zero;
IntPtr hMenu = IntPtr.Zero;
IContextMenu contextMenu = null;
IShellFolder shellFolder = null;
try
{
malloc = GetMalloc();
var hr = SHParseDisplayName(fileName, IntPtr.Zero, out var pidl, 0, out _);
if (hr != 0) throw new Exception("SHParseDisplayName failed");
originalPidl = pidl;
var guid = typeof(IShellFolder).GUID;
hr = SHBindToParent(pidl, guid, out pShellFolder, ref pidl);
if (hr != 0) throw new Exception("SHBindToParent failed");
shellFolder = (IShellFolder)Marshal.GetTypedObjectForIUnknown(pShellFolder, typeof(IShellFolder));
hr = shellFolder.GetUIObjectOf(
IntPtr.Zero, 1, new[] { pidl }, typeof(IContextMenu).GUID, IntPtr.Zero, out pContextMenu
);
if (hr != 0) throw new Exception("GetUIObjectOf failed");
contextMenu = (IContextMenu)Marshal.GetTypedObjectForIUnknown(pContextMenu, typeof(IContextMenu));
hMenu = CreatePopupMenu();
contextMenu.QueryContextMenu(hMenu, 0, ContextMenuStartId, ContextMenuEndId, (uint)ContextMenuFlags.Explore);
var directory = Path.GetDirectoryName(fileName);
var invokeCommandInfo = new CMINVOKECOMMANDINFO
{
cbSize = (uint)Marshal.SizeOf(typeof(CMINVOKECOMMANDINFO)),
fMask = (uint)ContextMenuInvokeCommandFlags.Unicode,
hwnd = IntPtr.Zero,View on GitHub (pinned to 7fc63b07bb)
Solutions
- Preserve the HRESULT: throw new COMException("SHBindToParent failed", hr) so the failure code surfaces.
- Reject CLSID-style paths (:: prefix) and known namespace roots before invoking the helper, since those have no file-system parent.
- Validate the parent path with Directory.Exists(Path.GetDirectoryName(fileName)) for file-system items before calling.
- Re-resolve the PIDL from the display name immediately before binding to avoid stale-PIDL races.
Example fix
// before
hr = SHBindToParent(pidl, guid, out pShellFolder, ref pidl);
if (hr != 0) throw new Exception("SHBindToParent failed");
// after
hr = SHBindToParent(pidl, guid, out pShellFolder, ref pidl);
if (hr != 0) throw new COMException("SHBindToParent failed", hr); Defensive patterns
Strategy: validation
Validate before calling
if (fileName.StartsWith("::"))
throw new InvalidOperationException("Namespace-root paths have no parent IShellFolder.");
var parent = Path.GetDirectoryName(fileName);
if (!Directory.Exists(parent))
throw new DirectoryNotFoundException($"Parent folder does not exist: {parent}"); Type guard
static bool HasFileSystemParent(string path) => !path.StartsWith("::") && Directory.Exists(Path.GetDirectoryName(path)); Try / catch
try { ShellContextMenuDisplayHelper.ExecuteContextMenuItem(fileName, menuItemId); }
catch (Exception ex) when (ex.Message == "SHBindToParent failed") { logger.Warn($"No bindable parent for {fileName}"); /* skip action */ } Prevention
- Reject CLSID/namespace-root paths before invoking.
- Validate the parent directory exists.
- Preserve the HRESULT for diagnosability.
- Avoid holding PIDLs across long-running operations.
When it happens
Trigger: Binding against root pseudo-folders whose parent cannot be expressed as IShellFolder (e.g. the Desktop root, ::{CLSID} namespace roots), PIDLs that the Shell considers malformed for binding even though they parsed, item whose parent folder is a per-user virtual location that is not mounted in this session, or the PIDL memory was mutated between the two calls.
Common situations: User right-clicks a top-level namespace item (This PC, Recycle Bin, Network), or a control-panel CLSID path returned by a search engine; the file was renamed/moved in the same window of time so the parent no longer matches; running under an account whose profile did not finish loading so the user's Desktop parent is missing.
Related errors
- SHParseDisplayName failed
- GetUIObjectOf failed
- InvokeCommand failed with code {hr:X}
- Failed to delete HBitmap.
- Failed to get the desktop shell folder
AI-assisted analysis of Flow-Launcher/Flow.Launcher@7fc63b07bb (2026-08-13).
Data as JSON: /api/errors/62a589d3d8b725ba.
Report an issue: GitHub.