fix: fail immediately on non-retriable navigation errors#4976
fix: fail immediately on non-retriable navigation errors#4976andrewneilson wants to merge 1 commit intoSkyvern-AI:mainfrom
Conversation
97183ef to
f97994e
Compare
AronPerez
left a comment
There was a problem hiding this comment.
Auto-Review: PR #4976
Build Status
- All CI checks pass.
Findings Summary
- 1 bug (see inline comment) — outer retry loop undermines the non-retriable logic
- 1 suggestion (see inline comment) — tests duplicate production logic
- Good idea with clean implementation, but an existing outer retry loop will still retry non-retriable errors.
Agreement with Claude's Review
- No Claude review found.
Reviewed by AronPerez's auto-reviewer
skyvern/webeye/real_browser_state.py
Outdated
| error_str = str(e) | ||
|
|
||
| if any(pattern in error_str for pattern in NON_RETRIABLE_NAV_ERRORS): | ||
| LOG.warning( |
There was a problem hiding this comment.
Bug: The outer retry in get_or_create_page (further down in this file) catches any exception whose str() contains "net::ERR" and retries by closing the browser context. Since FailedToNavigateToUrl embeds the original error in its message (e.g., "Failed to navigate to url ... Error message: net::ERR_NAME_NOT_RESOLVED"), these non-retriable errors will still be caught and retried at the get_or_create_page level — partially defeating the purpose of this PR. Consider either:
- Having
get_or_create_pagere-raiseFailedToNavigateToUrlwithout retrying, or - Adding the non-retriable check there as well.
There was a problem hiding this comment.
Thanks for catching that. I ended up not disabling the outer retry for all of the error types in question since the two layers serve different purposes:
navigate_with_retry()retries in the same page/context/proxy, which is not useful forERR_NAME_*,
ERR_CERT_*, andERR_SSL_*- the outer
get_or_create_page()retry recreates the browser context, which is the only path that can pick a different proxy node. DNS/TLS failures can be proxy-specific so fully skipping the outer retry would turn recoverable proxy failures into immediate task failures. - I've kept permanent errors (currently just
ERR_INVALID_URL) in a separate category that skips both
| from skyvern.constants import NON_RETRIABLE_NAV_ERRORS | ||
| from skyvern.exceptions import FailedToNavigateToUrl | ||
|
|
||
|
|
There was a problem hiding this comment.
Suggestion: These tests re-implement navigate_to_url's retry logic in a local helper rather than testing the real RealBrowserState.navigate_to_url. If the production code changes its retry behavior, these tests will still pass. Consider mocking the heavy dependencies and testing the real method, or extracting the retry logic into a standalone testable function.
Also worth considering: adding net::ERR_SSL_ to the non-retriable patterns in constants.py — errors like ERR_SSL_PROTOCOL_ERROR indicate equally non-retriable TLS incompatibilities.
f97994e to
8ac1a61
Compare
|
made these changes to address feedback: |
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
8ac1a61 to
8cb76d3
Compare
Summary
ERR_INVALID_URLERR_NAME_NOT_RESOLVED,ERR_NAME_RESOLUTION_FAILED,ERR_CERT_*,ERR_SSL_*net::ERRfailuresnavigate_with_retry()get_or_create_page()for proxy-sensitive and transienterrors, since recreating the browser context may recover by selecting a different proxy node
ERR_INVALID_URLnow bypass both retry layersFailedToNavigateToUrl.error_messagein the outer retry path when available instead of relying onstr(e)Test plan
ruff check skyvern/constants.py skyvern/webeye/navigation.py skyvern/webeye/real_browser_state.py tests/unit_tests/webeye/test_navigation_retry.pyruff format --check skyvern/constants.py skyvern/webeye/navigation.py skyvern/webeye/ real_browser_state.py tests/unit_tests/webeye/test_navigation_retry.pynet::ERRerrors🤖 Generated with Claude Code