Skip to content

[Bug]: Closing a server preview tab never fires beforeunload or pagehide #23513

Closed

Description

@DavidMendesOS

Before submitting

  • I searched existing issues and did not find a duplicate.
  • I included enough detail to reproduce or investigate the problem.

Area

apps/server

Steps to reproduce

  1. Serve a local page that reports its unload events:
    <button>A</button>
    <script>
      for (const type of ["beforeunload", "pagehide", "visibilitychange"])
        addEventListener(type, () => navigator.sendBeacon(`/beacon?${type}`));
    </script>
  2. preview_open it, and optionally preview_click the button (user activation).
  3. t3_preview_close the tab.
  4. Check the server log for beacons.

Expected behavior

Closing the tab runs the page's unload lifecycle, as closing a tab in a normal browser does, so pages that save or report state on pagehide/beforeunload behave the same under agent testing.

Actual behavior

No beacon arrives for any of the three events, with or without the prior click. dropTab (apps/server/src/preview/ServerBrowser.ts:675 on 680152e) calls tab.page.close(). Playwright's default is runBeforeUnload: false, which closes the page without running unload handlers.

Impact

Minor bug or occasional failure

Version or commit

T3 Code (Beta) 0.1.1 desktop; code reference from main @ 680152e

Environment

macOS 26.6.2, server-side preview (Playwright engine)

Workaround

None found.

Notes on a fix

page.close({ runBeforeUnload: true }) alone is not enough. With it, a page whose beforeunload handler calls preventDefault() raises a beforeunload dialog and stays open until that dialog is answered. T3 only records dialogs for preview_dialog, so the close would hang on a dialog no one answers. The close path would also need to accept that dialog (or decide not to). That changes what closing a tab means for pages with unsaved-changes guards, so I'd like to know the intended behaviour before proposing a PR:

  • Should closing a tab (agent tool, Browser panel, idle close) run unload handlers at all?
  • If so, should a beforeunload prompt during close be accepted automatically, or reported back to the caller like other dialogs?

Filed by Claude Code (claude-opus-5-5) for @DavidMendesOS.

Activity

  1. NikitaMGrimm commented on Nov 3, 2026

    @NikitaMGrimm
    Contributor

    Note

    🤖 Claude Opus 5.5 reported on behalf of NikitaMGrimm

    Another reproduction on the desktop path, where the impact is losing a site's login.

    Environment: Windows 11, T3 Code 0.1.7-nightly.20261102 (my fork's build; same tab.desktop.close() close path as main at b7ab02e), serverPageMode: native, default profile.

    Test on example.com: I registered beforeunload, pagehide, unload and visibilitychange listeners that each write a localStorage key.

    Action Keys written by the listeners Key set before the action
    Navigate the tab All four n/a
    t3_preview_close, then reopen None Still there

    So the events either don't fire or their writes never land. I didn't test closing a tab by hand from the UI.

    Impact: a signed-in Discord tab stayed signed in across navigation. After t3_preview_close, reopening Discord showed "Please log in again": the token localStorage key was gone, while the account's entry in MultiAccountStore remained. I believe Discord writes its token back during unload, but I haven't confirmed that.

    This matters for agents in particular, because they're told to close the tabs they open, and the close reports success. The user finds out at their next visit.

    #23537 only changes the headless branch, so this path stays as it is. Should desktop tabs run unload handlers on close too?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions