{"record":{"id":"9c35ad95b29bcb19","repo":"jstedfast/MailKit","slug":"failed-to-resolve-host-0","errorCode":null,"errorMessage":"Failed to resolve host: {0}","messagePattern":"Failed to resolve host: (.+?)","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"MailKit/Net/SocketUtils.cs","lineNumber":171,"sourceCode":"\n\t\t\t\t\treturn socket;\n\t\t\t\t} catch (OperationCanceledException) {\n\t\t\t\t\tthrow;\n\t\t\t\t} catch (Exception ex) {\n\t\t\t\t\tif (!cancellationToken.CanBeCanceled) {\n#if NET6_0_OR_GREATER\n\t\t\t\t\t\tTelemetry.Socket.Metrics?.RecordConnectFailed (connectStartTicks, ipAddresses[i], host, port, false, ex);\n#endif\n\n\t\t\t\t\t\tsocket.Dispose ();\n\t\t\t\t\t}\n\n\t\t\t\t\tif (i + 1 == ipAddresses.Length)\n\t\t\t\t\t\tthrow;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthrow new IOException (string.Format (\"Failed to resolve host: {0}\", host));\n\t\t}\n\n\t\tpublic static async Task<Socket> ConnectAsync (string host, int port, IPEndPoint? localEndPoint, CancellationToken cancellationToken)\n\t\t{\n\t\t\tcancellationToken.ThrowIfCancellationRequested ();\n\n#if NET6_0_OR_GREATER\n\t\t\tvar ipAddresses = await Dns.GetHostAddressesAsync (host, cancellationToken).ConfigureAwait (false);\n#else\n\t\t\tvar ipAddresses = await Dns.GetHostAddressesAsync (host).ConfigureAwait (false);\n#endif\n\n\t\t\tfor (int i = 0; i < ipAddresses.Length; i++) {\n\t\t\t\tcancellationToken.ThrowIfCancellationRequested ();\n\n\t\t\t\tvar socket = new Socket (ipAddresses[i].AddressFamily, SocketType.Stream, ProtocolType.Tcp);\n\n\t\t\t\ttry {","sourceCodeStart":153,"sourceCodeEnd":189,"githubUrl":"https://github.com/jstedfast/MailKit/blob/9d3859a7855e3e17582c07fd01972b8e262bf176/MailKit/Net/SocketUtils.cs#L153-L189","documentation":"SocketUtils.Connect resolves the host via DNS and tries each returned IP address; if resolution returns no usable addresses (or all connect attempts were skipped because the list was empty), it throws IOException(\"Failed to resolve host: <host>\"). Note this is the empty-resolution path — a thrown DNS exception is rethrown instead.","triggerScenarios":"Calling SmtpClient/Pop3/Imap Connect (sync path) with a hostname that DNS cannot resolve to any address, so ipAddresses.Length == 0.","commonSituations":"Typo in hostname; DNS outage or misconfigured resolver (e.g. in containers/Docker networks); host removed from DNS; corporate DNS blocking external lookups; offline machine.","solutions":["Verify the hostname with nslookup/dig from the same environment","Fix DNS configuration (resolver addresses, /etc/resolv.conf, VPN or corporate DNS)","Use an IP address directly (with certificate validation implications) or correct the hostname in config","Add network connectivity/DNS checks before connecting and handle IOException with a clear message"],"exampleFix":"// before\nclient.Connect(\"smtp.exampl.com\", 587); // typo -> IOException: Failed to resolve host\n// after\nclient.Connect(\"smtp.example.com\", 587);","handlingStrategy":"validation","validationCode":"// validate before connecting\nvar host = new Uri(smtpUri).Host;\nvar addresses = await Dns.GetHostAddressesAsync(host);\nif (addresses.Length == 0) throw new ArgumentException($\"Cannot resolve {host}\");","typeGuard":null,"tryCatchPattern":"try\n{\n    client.Connect(host, port, SecureSocketOptions.Auto);\n}\ncatch (IOException ex) when (ex.Message.StartsWith(\"Failed to resolve host\"))\n{\n    logger.LogError(\"DNS failure for {Host}: {Message}\", host, ex.Message);\n}","preventionTips":["Validate hostnames in config at startup (test resolution)","Watch for container/VPN DNS misconfiguration","Prefer explicit resolvable hostnames over stale records","Monitor DNS health in deployment environments"],"tags":["dns","network","smtp","resolve"],"backgroundTag":"network-request-failed","analyzedSha":"9d3859a7855e3e17582c07fd01972b8e262bf176","analyzedAt":"2026-09-15T15:46:11.592Z","contentChangedAt":"2026-09-15T15:46:11.592Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}