larksuite/cli · error
URL host is required
Error message
URL host is required
What it means
resolveDownloadHost normalizes the URL host and requires a non-empty value before performing DNS lookups for SSRF checks. An empty host means the URL had no authority component (or only a fragment/query), so no target can be resolved. Called by ValidateDownloadSourceURL and RoundTrip.
Source
Thrown at internal/validate/url.go:98
// ValidateDownloadSourceURL validates a download URL and blocks local/internal targets.
func ValidateDownloadSourceURL(ctx context.Context, rawURL string) error {
u, err := url.Parse(rawURL)
if err != nil || u == nil {
return fmt.Errorf("invalid URL")
}
if u.Scheme != "http" && u.Scheme != "https" {
return fmt.Errorf("only http/https URLs are supported")
}
_, err = resolveDownloadHost(ctx, u.Hostname(), net.DefaultResolver.LookupIP)
return err
}
type downloadLookupIPFunc func(context.Context, string, string) ([]net.IP, error)
func resolveDownloadHost(ctx context.Context, rawHost string, lookupIP downloadLookupIPFunc) ([]net.IP, error) {
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 {View on GitHub (pinned to 7fd6ef3c07)
Solutions
- Include the full host in the URL: https://example.com/path, not https:///path.
- Verify any templated/host variable was actually set before expansion.
- Re-copy the URL from the original source in full.
- Validate locally: `python3 -c "import urllib.parse,sys; print(urllib.parse.urlparse(sys.argv[1]).hostname)" "$URL"` should print a host.
Example fix
// before
HOST=""
lark-cli download url "https://$HOST/file.pdf"
// after
: "${HOST:?HOST must be set}"
lark-cli download url "https://$HOST/file.pdf" Defensive patterns
Strategy: validation
Validate before calling
u, err := url.Parse(rawURL)
if err != nil || strings.TrimSpace(u.Hostname()) == "" {
return fmt.Errorf("URL must include a host")
} Try / catch
if err := validate.ValidateDownloadSourceURL(ctx, raw); err != nil {
if strings.Contains(err.Error(), "URL host is required") {
return fmt.Errorf("URL is missing its host; include the full domain: %w", err)
}
return err
} Prevention
- Always include the full domain: scheme://host/path.
- Fail fast on unset variables used to build URLs (: "${HOST:?").
- Re-copy truncated URLs from the original source.
- Check u.Hostname() in your own tooling before handing URLs to the CLI.
When it happens
Trigger: resolveDownloadHost receives rawHost that is empty after TrimSpace/ToLower — i.e. the parsed URL had no host, e.g. "https://" alone, or a URL like "https:///path".
Common situations: Truncated URLs where the domain was cut off during copy-paste, template variables that failed to expand ("https://$HOST/file" with HOST unset), or malformed links from documents.
Related errors
- invalid URL
- only http/https URLs are supported
- blocked download target: local/internal host is not allowed
- Invalid cell reference: {cell_ref}
- Invalid A1 range endpoint: {endpoint}
AI-assisted analysis of larksuite/cli@7fd6ef3c07 (2026-09-04).
Data as JSON: /api/errors/7583134b7eede497.
Report an issue: GitHub.