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

  1. Preserve the HRESULT: throw new COMException("SHBindToParent failed", hr) so the failure code surfaces.
  2. Reject CLSID-style paths (:: prefix) and known namespace roots before invoking the helper, since those have no file-system parent.
  3. Validate the parent path with Directory.Exists(Path.GetDirectoryName(fileName)) for file-system items before calling.
  4. 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

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


AI-assisted analysis of Flow-Launcher/Flow.Launcher@7fc63b07bb (2026-08-13). Data as JSON: /api/errors/62a589d3d8b725ba. Report an issue: GitHub.