diff --git a/CHANGES/9451.bugfix.rst b/CHANGES/9451.bugfix.rst new file mode 100644 index 00000000000..2adcbc66273 --- /dev/null +++ b/CHANGES/9451.bugfix.rst @@ -0,0 +1 @@ +Fixed error messages from :py:class:`~aiohttp.resolver.AsyncResolver` being swallowed -- by :user:`bdraco`. diff --git a/aiohttp/resolver.py b/aiohttp/resolver.py index daa90b828c6..1025df06398 100644 --- a/aiohttp/resolver.py +++ b/aiohttp/resolver.py @@ -100,7 +100,7 @@ async def resolve( ) except aiodns.error.DNSError as exc: msg = exc.args[1] if len(exc.args) >= 1 else "DNS lookup failed" - raise OSError(msg) from exc + raise OSError(None, msg) from exc hosts: List[ResolveResult] = [] for node in resp.nodes: address: Union[Tuple[bytes, int], Tuple[bytes, int, int, int]] = node.addr @@ -134,7 +134,7 @@ async def resolve( ) if not hosts: - raise OSError("DNS lookup failed") + raise OSError(None, "DNS lookup failed") return hosts diff --git a/tests/test_resolver.py b/tests/test_resolver.py index 8ca7d329264..701f0a453a3 100644 --- a/tests/test_resolver.py +++ b/tests/test_resolver.py @@ -315,6 +315,34 @@ async def test_async_resolver_ipv6_positive_lookup(loop: Any) -> None: ) +@pytest.mark.skipif(not getaddrinfo, reason="aiodns >=3.2.0 required") +async def test_async_resolver_error_messages_passed( + loop: asyncio.AbstractEventLoop, +) -> None: + """Ensure error messages are passed through from aiodns.""" + with patch("aiodns.DNSResolver", autospec=True, spec_set=True) as mock: + mock().getaddrinfo.side_effect = aiodns.error.DNSError(1, "Test error message") + resolver = AsyncResolver() + with pytest.raises(OSError, match="Test error message") as excinfo: + await resolver.resolve("x.org") + + assert excinfo.value.strerror == "Test error message" + + +@pytest.mark.skipif(not getaddrinfo, reason="aiodns >=3.2.0 required") +async def test_async_resolver_error_messages_passed_no_hosts( + loop: asyncio.AbstractEventLoop, +) -> None: + """Ensure error messages are passed through from aiodns.""" + with patch("aiodns.DNSResolver", autospec=True, spec_set=True) as mock: + mock().getaddrinfo.return_value = fake_aiodns_getaddrinfo_ipv6_result([]) + resolver = AsyncResolver() + with pytest.raises(OSError, match="DNS lookup failed") as excinfo: + await resolver.resolve("x.org") + + assert excinfo.value.strerror == "DNS lookup failed" + + async def test_async_resolver_aiodns_not_present(loop: Any, monkeypatch: Any) -> None: monkeypatch.setattr("aiohttp.resolver.aiodns", None) with pytest.raises(RuntimeError):