microsoft/autogen · error · ValueError

No such element.

Error message

No such element.

What it means

PlaywrightController.click_id() locates the element by its injected __elementId attribute and waits up to 5000 ms for it to appear; on timeout it raises ValueError('No such element.'). Element ids are assigned when the page snapshot was taken, so this almost always means the DOM changed between the LLM seeing the page and clicking — navigation, re-render, SPA update, or an iframe/context switch invalidated the id.

Source

Thrown at python/packages/autogen-ext/src/autogen_ext/agents/web_surfer/playwright_controller.py:362

        """
        Click the element with the given identifier.

        Args:
            page (Page): The Playwright page object.
            identifier (str): The element identifier.

        Returns:
            Page | None: The new page if a new page is opened, otherwise None.
        """
        new_page: Page | None = None
        assert page is not None
        target = page.locator(f"[__elementId='{identifier}']")

        # See if it exists
        try:
            await target.wait_for(timeout=5000)
        except TimeoutError:
            raise ValueError("No such element.") from None

        # Click it
        await target.scroll_into_view_if_needed()
        await asyncio.sleep(0.3)

        box = cast(Dict[str, Union[int, float]], await target.bounding_box())

        if self.animate_actions:
            await self.add_cursor_box(page, identifier)
            # Move cursor to the box slowly
            start_x, start_y = self.last_cursor_position
            end_x, end_y = box["x"] + box["width"] / 2, box["y"] + box["height"] / 2
            await self.gradual_cursor_animation(page, start_x, start_y, end_x, end_y)
            await asyncio.sleep(0.1)

            try:
                # Give it a chance to open a new page
                async with page.expect_event("popup", timeout=1000) as page_info:  # type: ignore

View on GitHub (pinned to 027ecf0a37)

Solutions

  1. Re-observe the page (take a new snapshot / call the observe step) and use a fresh target_id
  2. Catch the ValueError and retry the click after the page settles (wait_for_load_state + sleep)
  3. Ensure the model always requests fresh page state before interacting after any navigation
  4. Pass correct target_id values; validate the id exists in the current rects before clicking

Example fix

// before
await controller.click_id(page, old_target_id)  # stale after navigation

// after
try:
    await controller.click_id(page, target_id)
except ValueError:
    rects = await surfer._get_visual_rects(...)  # refresh state
    target_id = pick_new_id(rects)
    await controller.click_id(page, target_id)
Defensive patterns

Strategy: retry

Validate before calling

async def target_exists(page, identifier: str) -> bool:
    locator = page.locator(f"[__elementId='{identifier}']")
    try:
        await locator.wait_for(timeout=1000)
        return True
    except TimeoutError:
        return False

Try / catch

try:
    new_page = await controller.click_id(page, target_id)
except ValueError as e:
    if 'No such element' in str(e):
        await page.wait_for_load_state()
        # re-snapshot page, pick a fresh target_id, then retry once
        raise StaleElementException('re-observe page before clicking') from e
    raise

Prevention

When it happens

Trigger: click_id(page, target_id) where target_id came from an older snapshot: after page navigation, dynamic content replaced the node, the element was inside a shadow DOM/iframe not re-tagged, or the id string itself is malformed (e.g. 'None' from str(args.get('target_id')) on a missing arg).

Common situations: Clicking on reactive sites (React/Vue re-renders), popups/dialogs covering content, slow-loading pages where the snapshot was taken too early, agents reusing ids across steps.

Related errors


AI-assisted analysis of microsoft/autogen@027ecf0a37 (2026-08-15). Data as JSON: /api/errors/8938807349a36a67. Report an issue: GitHub.