Flow-Launcher/Flow.Launcher · error · Exception
SHParseDisplayName failed
Error message
SHParseDisplayName failed
What it means
Thrown when the Win32 shell32 function SHParseDisplayName returns a non-zero HRESULT for the user-supplied file name. SHParseDisplayName converts a display name (e.g. an absolute path or shell namespace URL) into a PIDL that the rest of the Shell COM API consumes; a non-zero HRESULT means the Shell namespace could not resolve the name to an item. The exception intentionally discards the HRESULT, so the original failure code is lost. It is raised inside ExecuteContextMenuItem, which builds and invokes a Windows Explorer context menu for a file/folder.
Source
Thrown at Plugins/Flow.Launcher.Plugin.Explorer/Helper/ShellContextMenuDisplayHelper.cs:186
SHGetMalloc(out var pMalloc);
return (IMalloc)Marshal.GetTypedObjectForIUnknown(pMalloc, typeof(IMalloc));
}
public static void ExecuteContextMenuItem(string fileName, uint menuItemId)
{
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);
View on GitHub (pinned to 7fc63b07bb)
Solutions
- Before calling ExecuteContextMenuItem, validate with File.Exists(fileName) || Directory.Exists(fileName) and surface a user-facing message instead of throwing.
- Capture and propagate the HRESULT: throw new COMException("SHParseDisplayName failed", hr) so callers can branch on E_INVALIDARG vs STG_E_FILENOTFOUND.
- Normalise the path (Path.GetFullPath, replace '/' with '\', expand environment variables) before invoking the helper.
- Handle COMException/Exception at the call site and log fileName plus the HRESULT so future reports are actionable.
Example fix
// before
var hr = SHParseDisplayName(fileName, IntPtr.Zero, out var pidl, 0, out _);
if (hr != 0) throw new Exception("SHParseDisplayName failed");
// after
var hr = SHParseDisplayName(fileName, IntPtr.Zero, out var pidl, 0, out _);
if (hr != 0) throw new COMException($"SHParseDisplayName failed for '{fileName}'", hr); Defensive patterns
Strategy: validation
Validate before calling
if (string.IsNullOrWhiteSpace(fileName) || fileName.Contains('/')) fileName = fileName.Replace('/', '\\');
if (!File.Exists(fileName) && !Directory.Exists(fileName))
throw new FileNotFoundException($"Shell item does not exist: {fileName}", fileName); Type guard
static bool IsResolvableShellPath(string path) => !string.IsNullOrWhiteSpace(path) && (File.Exists(path) || Directory.Exists(path) || path.StartsWith("::")); Try / catch
try { ShellContextMenuDisplayHelper.ExecuteContextMenuItem(fileName, menuItemId); }
catch (COMException ex) { logger.Error($"Shell op failed: 0x{ex.ErrorCode:X} for {fileName}"); }
catch (Exception ex) when (ex.Message == "SHParseDisplayName failed") { logger.Warn($"Unresolvable path: {fileName}"); } Prevention
- Validate the path exists before calling ExecuteContextMenuItem.
- Always pass absolute, backslash-separated, environment-expanded paths.
- Capture HRESULTs instead of throwing bare Exception so callers can branch.
- Re-resolve paths immediately before invoking to avoid stale-result races.
When it happens
Trigger: Calling ExecuteContextMenuItem(fileName, menuItemId) where fileName is null/empty, relative, uses forward slashes on a build where the Shell rejects them, points to a network/UNC path whose server is unreachable, references an item that has been deleted or moved since the result list was built, contains illegal characters, or is on a removable drive that has been ejected. SHParseDisplayName is also sensitive to long-path behavior and to per-user namespace extensions that may be unloaded.
Common situations: The file shown in Flow Launcher's result list is deleted by another process between the search and the right-click action; the user right-clicks a stale network share; the application runs under a context where the Desktop folder is not initialised; paths coming from a third-party search engine (Everything) exceed MAX_PATH and the long-path opt-in is off.
Related errors
- SHBindToParent 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/c47fe0c4b79dd823.
Report an issue: GitHub.