add retry for actions that fail due to page navigation mid-action (#2011)

This commit is contained in:
Nick Sweeting
2025-06-19 07:41:41 -07:00
committed by GitHub
3 changed files with 31 additions and 2 deletions

View File

@@ -353,7 +353,19 @@ class Registry(Generic[Context]):
# All functions are now normalized to accept kwargs only
# Call with params and unpacked special context
return await action.function(params=validated_params, **special_context)
try:
return await action.function(params=validated_params, **special_context)
except Exception as e:
# Retry once if it's a page error
logger.warning(f'⚠️ Action {action_name}() failed: {type(e).__name__}: {e}, trying one more time...')
special_context['page'] = browser_session and await browser_session.get_current_page()
try:
return await action.function(params=validated_params, **special_context)
except Exception as retry_error:
raise RuntimeError(
f'Action {action_name}() failed: {type(e).__name__}: {e} (page may have closed or navigated away mid-action)'
) from retry_error
raise
except ValueError as e:
# Preserve ValueError messages from validation

View File

@@ -1195,7 +1195,7 @@ class TestControllerIntegration:
# This should fail if page_extraction_llm is not passed correctly
with pytest.raises(RuntimeError) as exc_info:
await controller.act(ExtractContentActionModel(**extract_action), browser_session)
await controller.act(ExtractContentActionModel(**extract_action), browser_session, page_extraction_llm=None)
# Should fail because page_extraction_llm is required but not provided
assert 'page_extraction_llm' in str(exc_info.value)

View File

@@ -993,6 +993,23 @@ class TestParameterOrdering:
assert action.name == 'extract_content'
assert action.description == 'Extract content from page'
async def test_page_error_retry(self, registry, browser_session):
"""Test that page errors trigger retry with fresh page"""
call_count = 0
@registry.action('Flaky page action', param_model=SimpleParams)
async def flaky_action(params: SimpleParams, page: Page):
nonlocal call_count
call_count += 1
if call_count == 1:
raise RuntimeError('page closed')
return ActionResult(extracted_content=f'Success on attempt {call_count}')
# Should retry once and succeed
result = await registry.execute_action('flaky_action', {'value': 'test'}, browser_session=browser_session)
assert 'Success on attempt 2' in result.extracted_content
assert call_count == 2
class TestParamsModelArgsAndKwargs:
async def test_browser_session_double_kwarg(self):