Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Add DNSResolutionError for handling DNS resolution failures #360

Open
wants to merge 18 commits into
base: main
Choose a base branch
from

Conversation

devin-ai-integration[bot]
Copy link
Contributor

Description

This PR adds a new DNSResolutionError class to handle DNS resolution failures while maintaining security checks for invalid URLs. This addresses issue airbytehq/airbyte-internal-issues#11320.

Key changes:

  • Add DNSResolutionError class for DNS resolution failures
  • Keep InvalidURL as a config error for security validation
  • Add test coverage for both DNS resolution errors and invalid URLs

Link to Devin run: https://app.devin.ai/sessions/6b54ed98f6e84226b1f5a7cb2d1a941d
Requested by: AJ

devin-ai-integration bot and others added 14 commits February 20, 2025 19:57
Co-Authored-By: Aaron <AJ> Steers <[email protected]>
Co-Authored-By: Aaron <AJ> Steers <[email protected]>
Co-Authored-By: Aaron <AJ> Steers <[email protected]>
Copy link
Contributor Author

🤖 Devin AI Engineer

Original prompt from Aaron:

Received message in Slack channel #ask-devin-ai:

@Devin - Can you help me get started on this issue? <https://github.com/airbytehq/airbyte-internal-issues/issues/11320>

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add "(aside)" to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

devin-ai-integration bot and others added 2 commits February 20, 2025 20:15
Co-Authored-By: Aaron <AJ> Steers <[email protected]>
Co-Authored-By: Aaron <AJ> Steers <[email protected]>
@@ -59,3 +59,24 @@ class DefaultBackoffException(BaseBackoffException):

class RateLimitBackoffException(BaseBackoffException):
pass


class DNSResolutionError(BaseBackoffException):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see where this exception class is raised. Can you help me understand this?

Does our code need to raise this exception in order for its handling to trigger? Or is it going to be picked up automatically somehow?

Copy link
Contributor Author

The DNSResolutionError is raised in http_client.py's _send method when we catch a requests.ConnectionError that contains DNS-related error messages. Here's the relevant code:

try:
    response = self._session.send(request, **request_kwargs)
except requests.ConnectionError as e:
    if "Name or service not known" in str(e) or "nodename nor servname provided" in str(e):
        assert request.url is not None, "Request URL cannot be None for DNS resolution error"
        exc = DNSResolutionError(
            url=request.url, request=request, response=e, error_message=str(e)
        )
    else:
        exc = e

This allows us to distinguish between actual DNS resolution failures (which should be retried) and invalid URLs (which are config errors and should fail immediately). The error handler will then interpret this exception and apply the appropriate retry policy.

@@ -300,6 +301,16 @@ def _send(

try:
response = self._session.send(request, **request_kwargs)
except requests.ConnectionError as e:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we only catch InvalidURL exceptions here? It looks like previously, these failures were raised and custom-handled as InvalidURL exceptions.

Copy link
Contributor Author

We should catch here rather than because:

  1. is raised by requests when a URL is malformed (e.g., missing scheme, invalid characters)
  2. DNS resolution errors come as with specific error messages like 'Name or service not known'

The key difference is:

  • : Immediate validation failure for malformed URLs (config error)
  • with DNS message: Temporary failure to resolve a well-formed URL (transient error)

Previously, both were treated as , but this meant we weren't retrying on temporary DNS failures. This change allows us to:

  1. Fail fast on malformed URLs (security/config validation)
  2. Retry on temporary DNS resolution issues (improved reliability)

The error handler will then apply the appropriate retry policy based on the specific exception type.

Comment on lines +344 to +350
def test_dns_resolution_error_retry():
"""Test that DNS resolution errors are retried"""
stream = StubHttpStreamWithErrorHandler()
error_handler = stream.get_error_handler()
request = requests.PreparedRequest()
request.url = "https://example.com"
dns_error = DNSResolutionError(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add a test that simulates/mocks the error we expect the http api to raise? Specifically, I think we're expecting something like an invalid URL code, except with the noted error text about DNS.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working security
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant