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

  1. Ensure a live session with at least one open tab exists before the call: start Browser, navigate somewhere, then invoke the action.
  2. For tab-closing actions, guard with a check on remaining tab count before closing the last tab.
  3. 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

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


AI-assisted analysis of browser-use/browser-use@6c73fced2f (2026-08-14). Data as JSON: /api/errors/51043ebc609ffb37. Report an issue: GitHub.