Errors and timeouts
editExceptions
A DNS error code (NXDOMAIN, SERVFAIL, REFUSED, ...) is a response, not an exception: see Response codes. QueryAsync, ReverseLookupAsync and SendAsync throw when there is no usable response:
| Exception | Cause |
|---|---|
TimeoutException | No response within DnsClientOptions.Timeout. |
OperationCanceledException | The CancellationToken you passed was canceled. |
| DnsProtocolException | The response is malformed, or does not answer the query that was sent. |
SocketException, IOException | The transport failed: connection refused, reset, unreachable network (UDP, TCP, TLS, QUIC). |
HttpRequestException | The DNS over HTTPS request failed, including an HTTP error status. |
AuthenticationException | The TLS handshake failed, for instance because the certificate does not match the host name (DNS over TLS). |
ObjectDisposedException | The client was disposed. |
Timeout and cancellation
Timeout (5 seconds by default) bounds each call, including the retry over TCP of a truncated answer and the queries of local DNSSEC validation. When it elapses, the call throws TimeoutException; when your token is canceled, it throws OperationCanceledException, so you can tell them apart:
// The server never answers queries for slow.example.com
using var client = new DnsClient(serverAddress, DnsClientProtocol.Udp, new DnsClientOptions
{
Timeout = TimeSpan.FromSeconds(1),
});
await Assert.ThrowsAsync<TimeoutException>(() => client.QueryAsync("slow.example.com", DnsQueryType.A));Timeout.InfiniteTimeSpan disables the timeout; a zero or negative value throws ArgumentOutOfRangeException from the constructor. The client does not retry a query that timed out: catch TimeoutException to retry, or to try another server.
Response checks
Every response is checked against the query it answers: the transaction ID, the QR (response) flag, the opcode and the question must match, or the call throws DnsProtocolException. Over UDP, the socket is also connected to the server, so the operating system drops datagrams that come from another address. A stray or forged datagram cannot be taken for the answer.
These checks do not authenticate the server. Use an encrypted transport (Protocols) or DNSSEC when the answer must be trusted.
Tracing
The client emits an Activity named dns.query for each query, from the ActivitySource named Meziantou.Framework.DnsClient. Add the source to your OpenTelemetry configuration to trace the queries. The activity has the tags:
| Tag | Value |
|---|---|
dns.question.name, dns.question.type, dns.question.class | The question |
network.transport | The transport |
dns.response.code | The response code |
dns.dnssec.validation_status | The result of local DNSSEC validation, when enabled |
The status of the activity is Error for an exception or a response code other than NoError.