mRemoteNG/mRemoteNG · error · VaultOpenbaoException

Failed to resolve address '{address}'

Error message

Failed to resolve address '{address}'

What it means

Thrown by ReadOtpSSH's catch-all when Dns.GetHostAddressesAsync itself throws (rather than returning empty). The second argument (ex.Message) carries the underlying DNS exception text. It is the wrapper for any DNS-layer failure: socket error, timeout, DNS server unreachable.

Source

Thrown at ExternalConnectors/VO/VaultOpenbao.cs:61

                    throw new VaultOpenbaoException($"Backend of type ldap does not match expected type {VaultOpenbaoSecretEngine}");
                case "ssh" when VaultOpenbaoSecretEngine != 3:
                    throw new VaultOpenbaoException($"Backend of type ssh does not match expected type {VaultOpenbaoSecretEngine}");
            }
        }
        public static void ReadOtpSSH(string mount, string role, string? username, string address, out string password) {
            VaultClient vaultClient = GetClient();
            TestMountType(vaultClient, mount, 3);
            if (!IPAddress.TryParse(address, out _)) {
                try {
                    var addrs = Dns.GetHostAddressesAsync(address).Result;
                    if (addrs == null || addrs.Length == 0) {
                        throw new VaultOpenbaoException($"Could not resolve address '{address}'");
                    }
                    // Prefer IPv4, otherwise take first available
                    var selected = addrs.FirstOrDefault(a => a.AddressFamily == AddressFamily.InterNetwork) ?? addrs[0];
                    address = selected.ToString();
                } catch (Exception ex) {
                    throw new VaultOpenbaoException($"Failed to resolve address '{address}'", ex.Message);
                }
            }
            var otp = vaultClient.V1.Secrets.SSH.GetCredentialsAsync(role, address, username, mount).Result;
            password = otp.Data.Key;

        }
        public static void ReadPasswordSSH(int secretEngine, string mount, string role, string username, out string password) {
            VaultClient vaultClient = GetClient();
            TestMountType(vaultClient, mount, secretEngine);
            switch (secretEngine) {
                case 0:
                    var kv = vaultClient.V1.Secrets.KeyValue.V2.ReadSecretAsync(role, mountPoint: mount).Result;
                    password = kv.Data.Data[username].ToString() ?? string.Empty;
                    return;
                default:
                    throw new VaultOpenbaoException($"Backend of type {secretEngine} is not supported");
            }
        }

View on GitHub (pinned to 9211babf35)

Solutions

  1. Inspect the inner message (ex.Arguments / the second constructor arg) — it is the original DNS exception text and names the real cause (e.g., 'No such host is known').
  2. Retry once after a short delay for transient DNS/network failures.
  3. Verify network connectivity and DNS server reachability from the machine.
  4. Fall back to an IP address if the hostname is unreliable, bypassing DNS entirely (IPAddress.TryParse path).
  5. Catch VaultOpenbaoException and surface both the address and the inner DNS error to the user.

Example fix

// before
} catch (Exception ex) {
    throw new VaultOpenbaoException($"Failed to resolve address '{address}'", ex.Message);
}

// after
} catch (Exception ex) {
    throw new VaultOpenbaoException($"Failed to resolve address '{address}': {ex.Message}", ex.Message);
}
Defensive patterns

Strategy: retry

Validate before calling

// Wrap DNS resolution with a single retry for transient failures
static IPAddress[] ResolveWithRetry(string address)
{
    try { return Dns.GetHostAddresses(address); }
    catch (SocketException) { System.Threading.Thread.Sleep(500); return Dns.GetHostAddresses(address); }
}

Type guard

if (ex is VaultOpenbaoException v && v.Message.StartsWith("Failed to resolve")) { /* DNS-layer exception; check inner (v.Arguments) for cause */ }

Try / catch

try { VaultOpenbao.ReadOtpSSH(mount, role, username, address, out var pass); }
catch (VaultOpenbaoException ex) when (ex.Message.StartsWith("Failed to resolve"))
{ /* transient DNS or network: inspect ex.Arguments, optionally retry once */ }

Prevention

When it happens

Trigger: GetHostAddressesAsync throws SocketException (DNS server unreachable, transient network failure, hostname too long, malformed hostname), or any other Exception from the DNS layer.

Common situations: Network/DNS server outage at call time; no network connectivity (offline machine); transient DNS timeout under load; corporate DNS server temporarily down; hostname contains invalid characters.

Related errors


AI-assisted analysis of mRemoteNG/mRemoteNG@9211babf35 (2026-08-13). Data as JSON: /api/errors/5cc065f8775787c5. Report an issue: GitHub.