Skip to content

bug(material/select): click during hydration event replay throws "composedPath called during event replay" #33386

@benjam1337

Description

@benjam1337

Is this a regression?

  • Yes, this behavior used to work in the previous version

The previous version in which this bug was not present was

No response

Description

We're seeing errors in production when an app uses SSR with hydration and withEventReplay(). If a user clicks on a mat-select (inside a
mat-form-field) before hydration completes, the click is queued and replayed later, and the replay ends up throwing:

Error: `composedPath` called during event replay.

From what I can tell, Angular core intentionally patches composedPath on replayed events so that it throws, since the composed path is no longer available once browser dispatch is over (see event_dispatcher.ts#prepareEventForReplay).
Meanwhile, the CDK's _getEventTarget helper calls composedPath() unconditionally:

https://github.com/angular/components/blob/main/src/cdk/platform/features/shadow-dom.ts

export function _getEventTarget<T extends EventTarget>(event: Event): T | null {
  return (event.composedPath ? event.composedPath()[0] : event.target) as T | null;
}

The error surfaces through MatSelect.onContainerClick, which calls _getEventTarget(event) to check whether the click landed on an option or the overlay backdrop.

Reproduction

Reproduction repo: https://github.com/benjam1337/repro-cdk-composedpath

It's a vanilla ng new --ssr app (Angular 21.2, Material/CDK 21.2.2, live SSR via RenderMode.Server). The only tweaks, detailed in the README, are:

  • a mat-form-field + mat-select in the root component;
  • a 20-second artificial delay before client bootstrap in main.ts, to make
    the pre-hydration click window deterministic (in a real app this window
    exists on slow devices/networks).

Steps to reproduce:

  1. npm install && npm run build
  2. node dist/repro-cdk-composedpath/server/server.mjs and open http://localhost:4000 with the DevTools console open
  3. Click on the "Country" select within 20 seconds of page load (before hydration completes)
  4. Once hydration completes and the click is replayed, the error is thrown

Clicking after hydration works fine, only clicks queued during the pre-hydration window trigger the error.

(I went with a repo rather than StackBlitz because the repro needs the real SSR server + hydration flow, which I couldn't get working reliably there.)

Expected Behavior

The replayed click is handled gracefully and the select opens (or at least fails silently), without an error reaching the application ErrorHandler.

Actual Behavior

Error: `composedPath` called during event replay. is thrown, the replayed click appears to be lost, and the error propagates to the application ErrorHandler (so it gets reported to our error tracking for every affected user).

Environment

  • Angular: 21.2.6 (reproduced with 21.2.17 as well)
  • CDK/Material: 21.2.2
  • Browser(s): observed on Samsung Internet 30 (Android), Chrome Mobile, and others. Seems timing-dependent rather than browser-specific; reproduced locally in Chromium
  • Operating System: Android, iOS, Windows, macOS (production traffic); repro on macOS

Metadata

Metadata

Assignees

No one assigned

    Labels

    area: cdk/platformgemini-triagedLabel noting that an issue has been triaged by geminineeds triageThis issue needs to be triaged by the team

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions