Skip to content

fix(devtools): handle pointercancel when dragging the indicator - #98506

Merged
icyJoseph merged 3 commits into
canaryfrom
fix/devtools-draggable-pointer-capture
Sep 11, 2026
Merged

fix(devtools): handle pointercancel when dragging the indicator#98506
icyJoseph merged 3 commits into
canaryfrom
fix/devtools-draggable-pointer-capture

Conversation

@icyJoseph

@icyJoseph icyJoseph commented Sep 10, 2026

Copy link
Copy Markdown
Member

Fixes #98468

Claude explanation of the fix

useDrag listened for pointermove and pointerup, but never pointercancel.

When a user agent cancels a gesture — a browser or system gesture takes over, a second finger arrives — it fires pointercancel and no pointerup, implicitly releasing pointer capture as it does. So cancel() never ran: the state machine stayed { state: 'drag' } and cleanup.current was never invoked, leaving the pointermove/pointerup listeners on window.

The next pointerup anywhere on the page then hit those orphaned listeners, reached cancel() with the state still 'drag', and called releasePointerCapture() on a pointer that no longer existed — the reported NotFoundError. Each cancelled drag also leaked another listener pair.

This registers pointercancel alongside pointerup and removes it in the same cleanup, so the machine unwinds when a gesture is cancelled; and it releases pointer capture only when hasPointerCapture() says it is still held, which is preferable to try/catch swallowing genuine faults too.

Note touch-action: none (#97723) removed the common touch trigger, but not the defect: on canary a forced touchCancel still throws.

Screen.Recording.2026-09-10.at.17.04.00.mov

Fixed version

Screen.Recording.2026-09-10.at.17.05.11.mov

Browser checks

  • Chrome, as describe by the bug report
  • FF works fine pre and post fix (with and without the pointer simulation)
  • iOS safari simulator, before the fix, I can't see an error, but, the drag gets frozen, with this fix it works correctly
Screen.Recording.2026-09-10.at.17.13.07.mov

🤖 Generated with Claude Code

`useDrag` listened for pointermove/pointerup but not pointercancel. When
the user agent cancels a gesture, no pointerup arrives, so cancel() never
ran: the state machine stayed in 'drag' and the window listeners were
never removed. The next pointerup anywhere on the page then reached
cancel() and called releasePointerCapture() on a pointer that no longer
existed, throwing NotFoundError.

Register pointercancel alongside pointerup, remove it in the same
cleanup, and only release pointer capture that is still held.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@github-actions

github-actions Bot commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

Tests Passed

Commit: aa250c6

@icyJoseph
icyJoseph marked this pull request as ready for review September 10, 2026 14:56
Replays the two-gesture sequence from #98468: pointerdown, a move past the
drag threshold, pointercancel, then a later move and up. Asserts no uncaught
error and that the indicator stops following the pointer.

Pointer capture is owned by the user agent and cannot be driven from script,
so the three capture methods are stubbed to the post-cancel behaviour a real
browser exhibits: capture no longer held, and releasing it throws
NotFoundError.

With the fix reverted this is the only failing test in the directory, and it
fails with the error string from the issue.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@icyJoseph
icyJoseph marked this pull request as draft September 10, 2026 15:03
@icyJoseph
icyJoseph marked this pull request as ready for review September 10, 2026 15:15
It now handles pointercancel as well as pointerup, so the old name no
longer described what it does.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@icyJoseph
icyJoseph merged commit c5741d5 into canary Sep 11, 2026
218 of 220 checks passed
@icyJoseph
icyJoseph deleted the fix/devtools-draggable-pointer-capture branch September 11, 2026 14:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

next-devtools: Uncaught NotFoundError: Failed to execute 'releasePointerCapture' on 'Element' when dragging dev indicator on touch/mobile

2 participants