browser-use/browser-use · error · RuntimeError
Source element is not visible
Error message
Source element is not visible
What it means
A registered action declares `page` (a Playwright/Page-like object for a single tab) with no default, and the injected value was None. The page dependency is derived from the browser session's active tab, so None means there is no active page — session missing, closed, or all tabs closed.
Source
Thrown at browser_use/actor/element.py:602
# Create an Element for the option and click it
option_element = Element(self._browser_session, option_backend_id, self._session_id)
await option_element.click()
async def drag_to(
self,
target: Union['Element', Position],
source_position: Position | None = None,
target_position: Position | None = None,
) -> None:
"""Drag this element to another element or position."""
# Get source coordinates
if source_position:
source_x = source_position['x']
source_y = source_position['y']
else:
source_box = await self.get_bounding_box()
if not source_box:
raise RuntimeError('Source element is not visible')
source_x = source_box['x'] + source_box['width'] / 2
source_y = source_box['y'] + source_box['height'] / 2
# Get target coordinates
if isinstance(target, dict) and 'x' in target and 'y' in target:
target_x = target['x']
target_y = target['y']
else:
if target_position:
target_box = await target.get_bounding_box()
if not target_box:
raise RuntimeError('Target element is not visible')
target_x = target_box['x'] + target_position['x']
target_y = target_box['y'] + target_position['y']
else:
target_box = await target.get_bounding_box()
if not target_box:
raise RuntimeError('Target element is not visible')View on GitHub (pinned to 6c73fced2f)
Solutions
- Ensure a live session with at least one open tab exists before the call: start Browser, navigate somewhere, then invoke the action.
- For tab-closing actions, guard with a check on remaining tab count before closing the last tab.
- Pass page explicitly from the session's active page when orchestrating manually.
Example fix
# before result = await run_js(js='document.title') # page resolves to None # after page = await session.get_current_page() # ensure a tab is open result = await run_js(js='document.title', page=page)
Defensive patterns
Strategy: validation
Validate before calling
async def has_active_page(session) -> bool:
try:
page = await session.get_current_page()
return page is not None and not page.is_closed()
except Exception:
return False Type guard
def requires_page(func) -> bool:
import inspect, inspect as i
p = inspect.signature(func).parameters.get('page')
return p is not None and p.default is i.Parameter.empty Try / catch
try:
await action(**kwargs)
except ValueError as e:
if 'requires page' in str(e):
page = await session.get_current_page()
await action(**kwargs, page=page) Prevention
- Verify a tab is open before page-scoped actions.
- Depend on browser_session instead of page in custom actions for simpler wiring.
- Guard tab-closing logic so the last tab is never closed mid-run.
When it happens
Trigger: Calling a page-dependent action when browser_session is absent or has no active tab: browser not started, tab closed by a prior step, or direct invocation with page=None.
Common situations: Actions like 'evaluate on current page' invoked after close_tab closed the last tab; tests calling the action without a live browser; race where the action runs after the session shut down.
Related errors
- Session ID is required for fill operation
- Failed to fill element: {str(e)}
- Element is not visible or has no bounding box
- Target element is not visible
- JavaScript evaluation failed: {result["exceptionDetails"]}
AI-assisted analysis of browser-use/browser-use@6c73fced2f (2026-08-14).
Data as JSON: /api/errors/51043ebc609ffb37.
Report an issue: GitHub.