You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[Bug]: Preview browser cannot open native apps via custom-scheme deep links #16251
I searched existing issues and did not find a duplicate.
I included enough detail to reproduce or investigate the problem.
Area
apps/desktop
Steps to reproduce
Open a page you control in a preview tab (e.g. a local dev server).
From a click handler on that page, navigate to any custom scheme that has
a registered OS handler, e.g. location.href = "slack://open".
Observe the preview tab.
Expected behavior
The native app opens, the same as in a normal browser — or the handoff at
least visibly fails.
Actual behavior
Nothing happens. The deep link is dropped silently: no app launches, no
error, no log, and the preview stays on the current page. Any page that
waits for the native app (e.g. a "Launching… you will be redirected in a
few moments" interstitial) hangs forever.
Impact
Preview tabs cannot complete any flow that needs to open a desktop app.
changed the title [-][Bug]: Preview browser silently drops custom-scheme deep links, so SSO-to-desktop-app handoffs hang forever (slack://, zoom://, teams:// …)[/-][+][Bug]: Preview browser cannot open native apps via custom-scheme deep links[/+]on Oct 5, 2026
location.href = "slack://…" inside a preview guest is an external-protocol navigation. Electron 44 asks the session for the openExternal permission before launching the OS handler. The preview partition's permission handler in apps/desktop/src/preview/BrowserSession.ts allows clipboard read/write, notifications, and geolocation, but not openExternal, so the request is denied and Electron treats the navigation as handled. The page stays where it is, nothing is logged, and did-fail-load doesn't surface it (that handler also ignores ERR_ABORTED).
POPUP_PROTOCOLS / previewWindowOpenAction only decide whether window.open gets a popup. A slack:// target is classified as "navigate" and loaded back into the same guest, hitting the same denial.
setWindowOpenHandler and will-navigate in DesktopWindow.ts run on the app window, not the preview guest. parseSafeExternalUrl rejects slack:// there and also hides Copy Link in the guest context menu, so custom-scheme links can't be copied out either.
The address bar can't be used as a fallback: normalizePreviewUrl accepts only http:/https:, and the submit handler swallows that error. The hover-only "Open in system browser" button opens the current https page, though cookies stay in the preview partition. The preview ⋮ menu has no equivalent item (see closed PR feat(web): open the preview page in the system browser from the menu #10833).
Granting openExternal for every scheme would let any preview page launch arbitrary OS handlers without a prompt, so that's worth weighing against convenience.
Options include surfacing the denial visibly in the preview, with a user-initiated "Open" that routes through shell.openExternal (possibly scoped per scheme or per origin), and making "Open in system browser" and Copy Link available for custom-scheme links from the ⋮ and context menus.
Activity
[-][Bug]: Preview browser silently drops custom-scheme deep links, so SSO-to-desktop-app handoffs hang forever (slack://, zoom://, teams:// …)[/-][+][Bug]: Preview browser cannot open native apps via custom-scheme deep links[/+]juliusmarminge commentedon Oct 5, 2026
Note
Grok responding on behalf of Julius.
Triage
Thanks for the clear repro, @tensorcopy!
What I found
location.href = "slack://…"inside a preview guest is an external-protocol navigation. Electron 44 asks the session for theopenExternalpermission before launching the OS handler. The preview partition's permission handler inapps/desktop/src/preview/BrowserSession.tsallows clipboard read/write, notifications, and geolocation, but notopenExternal, so the request is denied and Electron treats the navigation as handled. The page stays where it is, nothing is logged, anddid-fail-loaddoesn't surface it (that handler also ignoresERR_ABORTED).POPUP_PROTOCOLS/previewWindowOpenActiononly decide whetherwindow.opengets a popup. Aslack://target is classified as"navigate"and loaded back into the same guest, hitting the same denial.setWindowOpenHandlerandwill-navigateinDesktopWindow.tsrun on the app window, not the preview guest.parseSafeExternalUrlrejectsslack://there and also hides Copy Link in the guest context menu, so custom-scheme links can't be copied out either.normalizePreviewUrlaccepts onlyhttp:/https:, and the submit handler swallows that error. The hover-only "Open in system browser" button opens the current https page, though cookies stay in the preview partition. The preview ⋮ menu has no equivalent item (see closed PR feat(web): open the preview page in the system browser from the menu #10833).Likely fix area
openExternalfor every scheme would let any preview page launch arbitrary OS handlers without a prompt, so that's worth weighing against convenience.shell.openExternal(possibly scoped per scheme or per origin), and making "Open in system browser" and Copy Link available for custom-scheme links from the ⋮ and context menus.A maintainer will decide on the fix direction.