Errors and timeouts

edit

Exceptions

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:

ExceptionCause
TimeoutExceptionNo response within DnsClientOptions.Timeout.
OperationCanceledExceptionThe CancellationToken you passed was canceled.
DnsProtocolExceptionThe response is malformed, or does not answer the query that was sent.
SocketException, IOExceptionThe transport failed: connection refused, reset, unreachable network (UDP, TCP, TLS, QUIC).
HttpRequestExceptionThe DNS over HTTPS request failed, including an HTTP error status.
AuthenticationExceptionThe TLS handshake failed, for instance because the certificate does not match the host name (DNS over TLS).
ObjectDisposedExceptionThe 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:

TagValue
dns.question.name, dns.question.type, dns.question.classThe question
network.transportThe transport
dns.response.codeThe response code
dns.dnssec.validation_statusThe result of local DNSSEC validation, when enabled

The status of the activity is Error for an exception or a response code other than NoError.