weaviate/weaviate · error

refusing to dial internal address %q

Error message

refusing to dial internal address %q

What it means

ssrfDialGuard blocks outbound connections whose resolved IP is internal (loopback, private ranges, link-local, etc.) via isDisallowedIP. Because it inspects the resolved ip:port, DNS names that resolve to internal addresses are also caught, defending against SSRF even when string-level URL validation passed.

Source

Thrown at usecases/modulecomponents/base_client.go:62

	return &http.Client{
		Transport: &retryTransport{base: transport, timeout: timeout},
		CheckRedirect: func(req *http.Request, via []*http.Request) error {
			return http.ErrUseLastResponse
		},
	}
}

// ssrfDialGuard blocks connections to internal addresses. address is the
// resolved "ip:port", so a host that resolves to an internal IP is caught here
// even if it slipped past ValidateBaseURL's string-level checks.
func ssrfDialGuard(network, address string, c syscall.RawConn) error {
	host, _, err := net.SplitHostPort(address)
	if err != nil {
		return fmt.Errorf("invalid dial address %q: %w", address, err)
	}
	if ip := net.ParseIP(host); ip != nil && isDisallowedIP(ip) {
		return fmt.Errorf("refusing to dial internal address %q", address)
	}
	return nil
}

View on GitHub (pinned to 75aa4b6d11)

Solutions

  1. Point the module baseUrl at a genuinely public, routable endpoint
  2. If the internal endpoint is intentional (self-hosted inference), deploy it on a routable address or use the supported configuration to allow it
  3. Check DNS resolution of the hostname — it may resolve to a private IP unexpectedly

Example fix

// before
baseURL := "http://127.0.0.1:8080"
// after
baseURL := "https://api.example-inference.com"
Defensive patterns

Strategy: validation

Validate before calling

u, err := url.Parse(baseURL)
if err != nil {
    return err
}
ips, err := net.LookupIP(u.Hostname())
if err != nil {
    return err
}
for _, ip := range ips {
    if ip.IsLoopback() || ip.IsPrivate() || ip.IsLinkLocalUnicast() {
        return fmt.Errorf("%s resolves to internal IP %s — will be blocked by SSRF guard", u.Host, ip)
    }
}

Try / catch

_, err := client.Do(req)
if err != nil && strings.Contains(err.Error(), "refusing to dial internal address") {
    return fmt.Errorf("endpoint blocked by SSRF protection; use a public endpoint: %w", err)
}

Prevention

When it happens

Trigger: The module client dials a host whose resolved IP is private/loopback/link-local — e.g. baseUrl set to localhost, 127.0.0.1, 10.x, 172.16-31.x, 192.168.x, 169.254.x, or a DNS name resolving to such an address.

Common situations: Local development pointing a vectorizer/generative module at localhost inference server; Kubernetes in-cluster service using cluster-internal IPs (cluster-local traffic blocked); DNS rebinding or misconfigured external hostname resolving to a private IP.

Related errors


AI-assisted analysis of weaviate/weaviate@75aa4b6d11 (2026-09-04). Data as JSON: /api/errors/2aeeae4382f2fb03. Report an issue: GitHub.