fix(click): report clicks on disabled form controls as errors - #5965
Open
yotambraun wants to merge 5 commits into
Open
yotambraun wants to merge 5 commits into
yotambraun wants to merge 5 commits into
Conversation
Contributor
There was a problem hiding this comment.
All reported issues were addressed across 2 files
Reply with feedback, questions, or to request a fix.
Fix all with cubic | Re-trigger cubic
Contributor
There was a problem hiding this comment.
All reported issues were addressed across 2 files (changes from recent commits).
Reply with feedback, questions, or to request a fix.
Fix all with cubic | Re-trigger cubic
Disabled form controls that have a click listener are offered to the agent, and click returned "Clicked ..." with no error although the browser never dispatches the click. Check the element's live :disabled state (including a disabled fieldset) and return a validation_error, as is already done for <select> and file inputs. The state is read live because the DOM snapshot can be stale after the page enables the control. aria-disabled is not blocked: the browser still delivers those clicks.
…on-form elements Add the disabled check to on_ClickCoordinateEvent next to the <select> and file-input checks (it is skipped with force=True, like the others), and return early from _is_element_disabled unless the element can match :disabled (form controls and form-associated custom elements), so other clicks make no extra CDP calls.
Move the index-path check from _click_element_node_impl into on_ClickElementEvent, before the print-button handling, so a disabled print control is reported instead of generating a PDF. Add a disabled print button test and make the test helper fail loudly when it cannot locate an element.
… actions input + click on a still-disabled button + input in one step: the queue now stops at the click; on main all three actions run and the second field is typed.
Controls are often enabled a moment after input (debounced checks). In agent runs the models that waited and retried after the error succeeded; the one that did not tried to force the control with page scripts instead. Say so in the message.
yotambraun
force-pushed
the
fix/click-disabled-elements
branch
from
October 2, 2026 14:48
d7bbc7a to
c863555
Compare
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #5964
Problem
A disabled form control that has a click listener is offered to the agent, and
clickon it returnsClicked button "..."with no error, although the browser never dispatches the click.is_interactive()returns early for elements with a click listener, before itsdisabledcheck, so these controls get an index. This includes framework buttons: a disabled Vue 3 button with@clickand a disabled React 18 button withonClickare both offered and reported as clicked. Witherrorunset,multi_act()keeps running the queued actions (it stops onerror), a single-action step is not counted towardmax_failures, and the model is told the click worked.Change
on_ClickElementEventnow checks the element's live:disabledstate (which includes a disabled<fieldset>) and returns avalidation_error, the same way file inputs and<select>are already handled, before the print-button special case, soclickreturnsActionResult(error=...).on_ClickCoordinateEventruns the same check next to its<select>and file-input checks (skipped withforce=True, like those). Only elements that can match:disabled(form controls and form-associated custom elements) are checked, so other clicks make no extra CDP calls:Deliberate limits:
disabledafter the page enables the control, so a snapshot check would block the type-then-click flow from multi_act() clicks wrong element when typing enables a previously-disabled button #4518. A test covers this.aria-disabledis not blocked: the browser still delivers those clicks and some pages react to them.Falseand the click proceeds as before.clicktool currently dispatches coordinate clicks withforce=True, so the coordinate-path check is exercised by the test rather than by the agent today; it is there so callers that useforce=Falseget the same answer.Which elements are offered to the agent is unchanged.
Before and after
Calling
clickon<button disabled>with a click listener (reproduction in #5964):errorextracted_contentNoneClicked button "Place order" id=placeCannot click element (index=3): it is disabled. ...NoneThe same before/after holds for a disabled Vue 3 (
@click) and React 18 (onClick) button.Demo
Captured from both builds on a real page (script and raw results in the evidence link below).
Tests
New
tests/ci/test_click_disabled_element.py(real headless Chromium, local pages):onclick="window.print()"):errormentions disabled and the handler did not run. On main these returnerror=NonewithClicked button ..., and for the print button a PDF is also generated.ClickCoordinateEvent,force=False) on a disabled and an enabled button:validation_errorvs clicked. The disabled case fails on main.aria-disabledelement: clicked as before.multi_actstep with input, click on the still-disabled button, input: the queue stops at the click and the second field stays empty. On main all three actions run.Checked locally:
uv run pytest tests/ci/test_click_disabled_element.py: 9 passed (5 of them fail on main)tests/ci(--numprocesses 4): 1222 passed, 39 skippedAgent runs
To see whether this changes normal agent behavior, I ran
browser_use.Agent(use_vision=False, max_steps=12) with gpt-4.1-mini, gpt-5.4-mini and gpt-5.6-luna against local checkout pages, on main and on this branch. An order counted only if the page's POST reached the test server. 60 runs in total.Clicked button "Create account". Orders 11/12 here vs 10/12 on main, and fewer repeated identical actions (11 vs 18). These samples are small, so I am not claiming an outcome difference from them.The protocol (written before the runs), scripts, per-step traces, token usage and the deterministic probes are in https://github.com/yotambraun/browser-use/tree/69c69ad6abdc474a2475d6cb10449571b5d49fac (its README has a summary table and reproduction steps).