larksuite/cli · error

failed to resolve host

Error message

failed to resolve host

What it means

DNS resolution of the download host failed: the lookupIP call (default net.DefaultResolver.LookupIP) returned an error, so resolveDownloadHost cannot verify the host is safe. The library deliberately discards the underlying DNS error and returns the opaque message "failed to resolve host" so callers get a uniform, non-leaking message. No IPs means no download and no SSRF risk can be assessed.

Source

Thrown at internal/validate/url.go:114

	host := strings.TrimSpace(strings.ToLower(rawHost))
	if host == "" {
		return nil, fmt.Errorf("URL host is required")
	}
	if host == "localhost" || strings.HasSuffix(host, ".localhost") {
		return nil, fmt.Errorf("local/internal host is not allowed")
	}
	if ip := net.ParseIP(host); ip != nil {
		if isRestrictedDownloadIP(ip) {
			return nil, fmt.Errorf("local/internal host is not allowed")
		}
		return []net.IP{ip}, nil
	}
	if lookupIP == nil {
		lookupIP = net.DefaultResolver.LookupIP
	}
	ips, err := lookupIP(ctx, "ip", host)
	if err != nil {
		return nil, fmt.Errorf("failed to resolve host")
	}
	if len(ips) == 0 {
		return nil, fmt.Errorf("failed to resolve host")
	}
	for _, ip := range ips {
		if isRestrictedDownloadIP(ip) {
			return nil, fmt.Errorf("local/internal host is not allowed")
		}
	}
	return ips, nil
}

// NewDownloadHTTPClient clones base client and enforces download-safe redirect
// and connection rules for untrusted URLs.
func NewDownloadHTTPClient(base *http.Client, opts DownloadHTTPClientOptions) *http.Client {
	if base == nil {
		base = &http.Client{}
	}

View on GitHub (pinned to 7fd6ef3c07)

Solutions

  1. Check the hostname spelling and confirm the domain actually exists (dig/nslookup with the same resolver).
  2. Verify DNS connectivity: test another domain, inspect /etc/resolv.conf, and fix resolver/VPN/firewall settings.
  3. Ensure the Go context passed in is not already cancelled or too short for a DNS round trip.
  4. Retry once connectivity is restored; transient resolver failures are common on flaky networks.
  5. If resolution genuinely fails for the whole network, fetch the file from a different, resolvable source.

Example fix

// before (host does not exist)
err := validate.ValidateDownloadSourceURL(ctx, "https://download.exmaple.com/file.zip")
// after (typo fixed)
err := validate.ValidateDownloadSourceURL(ctx, "https://download.example.com/file.zip")
Defensive patterns

Strategy: retry

Validate before calling

host := u.Hostname()
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
if _, err := net.DefaultResolver.LookupIP(ctx, "ip", host); err != nil {
    return fmt.Errorf("download host %q is not resolvable right now: %v", host, err)
}

Try / catch

ips, err := validateDownload(ctx, url)
if err != nil && strings.Contains(err.Error(), "failed to resolve host") {
    // check network/DNS, then retry with backoff
    time.Sleep(2 * time.Second)
    ips, err = validateDownload(ctx, url)
    if err != nil {
        return fmt.Errorf("download source %q unreachable: check DNS/network: %w", url, err)
    }
}

Prevention

When it happens

Trigger: ValidateDownloadSourceURL (or a proxied download RoundTrip) with a hostname the configured DNS resolver cannot resolve: NXDOMAIN, resolver timeout/cancellation via ctx, broken /etc/resolv.conf, no network, or a corporate VPN/DNS that refuses external lookups.

Common situations: Typo in the hostname; offline machine or flaky network; DNS server down or firewalled; inside a container with no DNS configured; VPN split-DNS hiding the domain; context cancelled mid-lookup; air-gapped CI runners.

Related errors


AI-assisted analysis of larksuite/cli@7fd6ef3c07 (2026-09-04). Data as JSON: /api/errors/6556d16c17e59e3b. Report an issue: GitHub.