diff --git a/airbyte_cdk/sources/streams/http/error_handlers/default_error_mapping.py b/airbyte_cdk/sources/streams/http/error_handlers/default_error_mapping.py index 74840e2d2..da616e0ee 100644 --- a/airbyte_cdk/sources/streams/http/error_handlers/default_error_mapping.py +++ b/airbyte_cdk/sources/streams/http/error_handlers/default_error_mapping.py @@ -19,9 +19,9 @@ error_message="Invalid Protocol Schema: The endpoint that data is being requested from is using an invalid or insecure. Exception: requests.exceptions.InvalidSchema", ), InvalidURL: ErrorResolution( - response_action=ResponseAction.FAIL, - failure_type=FailureType.config_error, - error_message="Invalid URL specified: The endpoint that data is being requested from is not a valid URL. Exception: requests.exceptions.InvalidURL", + response_action=ResponseAction.RETRY, + failure_type=FailureType.transient_error, + error_message="Invalid URL specified or DNS error occurred: The endpoint that data is being requested from is not a valid URL. Exception: requests.exceptions.InvalidURL", ), RequestException: ErrorResolution( response_action=ResponseAction.RETRY, diff --git a/unit_tests/sources/streams/http/test_http.py b/unit_tests/sources/streams/http/test_http.py index 40fdb3201..9f6209866 100644 --- a/unit_tests/sources/streams/http/test_http.py +++ b/unit_tests/sources/streams/http/test_http.py @@ -10,6 +10,7 @@ import pytest import requests +from requests.exceptions import InvalidURL from airbyte_cdk.models import AirbyteLogMessage, AirbyteMessage, Level, SyncMode, Type from airbyte_cdk.sources.streams import CheckpointMixin @@ -20,7 +21,10 @@ from airbyte_cdk.sources.streams.core import StreamData from airbyte_cdk.sources.streams.http import HttpStream, HttpSubStream from airbyte_cdk.sources.streams.http.error_handlers import ErrorHandler, HttpStatusErrorHandler -from airbyte_cdk.sources.streams.http.error_handlers.response_models import ResponseAction +from airbyte_cdk.sources.streams.http.error_handlers.response_models import ( + FailureType, + ResponseAction, +) from airbyte_cdk.sources.streams.http.exceptions import ( DefaultBackoffException, RequestBodyException, @@ -331,6 +335,20 @@ def test_raise_on_http_errors(mocker, error): assert send_mock.call_count == stream.max_retries + 1 +class StubHttpStreamWithErrorHandler(StubBasicReadHttpStream): + def get_error_handler(self) -> Optional[ErrorHandler]: + return HttpStatusErrorHandler(logging.getLogger()) + + +def test_dns_resolution_error_retry(): + """Test that DNS resolution errors are retried""" + stream = StubHttpStreamWithErrorHandler() + error_handler = stream.get_error_handler() + resolution = error_handler.interpret_response(InvalidURL()) + assert resolution.response_action == ResponseAction.RETRY + assert resolution.failure_type == FailureType.transient_error + + class PostHttpStream(StubBasicReadHttpStream): http_method = "POST"