micro/go-micro · error

push callback url has no host

Error message

push callback url has no host

What it means

defaultPushURLPolicy throws this error when the parsed push callback URL has an empty host component. A URL like 'https:///hook' or a relative path has nowhere to deliver push notifications, so the policy rejects it before any resolution or network use. Note the hostname() call strips the port, so a host must be a real DNS name or IP.

Source

Thrown at gateway/a2a/pushsecurity.go:40

// that passes validation cannot be rebound to an internal address before the
// connection is made. Operators who need to reach a trusted in-cluster
// receiver set Options.AllowPushURL to take over the policy.

// pushLookupIP resolves a host to IPs; overridable in tests.
var pushLookupIP = net.LookupIP

// defaultPushURLPolicy is the SSRF-safe policy applied when no AllowPushURL is
// configured. It rejects non-http(s) schemes and hosts that resolve to a
// loopback, private, link-local, multicast, or unspecified address.
func defaultPushURLPolicy(u *url.URL) error {
	switch u.Scheme {
	case "http", "https":
	default:
		return fmt.Errorf("push callback scheme %q not allowed (want http or https)", u.Scheme)
	}
	host := u.Hostname()
	if host == "" {
		return fmt.Errorf("push callback url has no host")
	}
	ips, err := resolvePushHost(host)
	if err != nil {
		return fmt.Errorf("push callback host %q: %w", host, err)
	}
	if len(ips) == 0 {
		return fmt.Errorf("push callback host %q did not resolve", host)
	}
	for _, ip := range ips {
		if blockedPushIP(ip) {
			return fmt.Errorf("push callback host %q resolves to a blocked address %s", host, ip)
		}
	}
	return nil
}

func resolvePushHost(host string) ([]net.IP, error) {
	if ip := net.ParseIP(host); ip != nil {

View on GitHub (pinned to 24529f1404)

Solutions

  1. Include a full authority in the callback URL: scheme://host[:port]/path.
  2. Check the environment/config value feeding the host portion of the URL (e.g. PUBLIC_HOST is unset).
  3. Pre-validate with url.Parse and require u.Hostname() != "" before calling the library.

Example fix

// before
u := os.Getenv("PUBLIC_HOST") // ""
callback := "https://" + u + "/a2a/push"
// after
if u == "" { return errors.New("PUBLIC_HOST must be set") }
callback := "https://" + u + "/a2a/push"
Defensive patterns

Strategy: validation

Validate before calling

u, err := url.Parse(callback)
if err != nil || u.Hostname() == "" {
	return fmt.Errorf("callback must include a host: %q", callback)
}

Type guard

func hasHost(u *url.URL) bool {
	return u != nil && u.Hostname() != ""
}

Prevention

When it happens

Trigger: Calling SetPushNotificationConfig with a URL whose authority is missing: 'https:///path', 'http://:8080/hook', or a bare path like '/webhook' that url.Parse accepts without error.

Common situations: Template/config substitution leaving an empty hostname (e.g. unset HOST env var interpolated into the URL); hand-built URL strings via concatenation; forgetting the domain when pasting a webhook.

Related errors


AI-assisted analysis of micro/go-micro@24529f1404 (2026-09-01). Data as JSON: /api/errors/8ea0353ad0405156. Report an issue: GitHub.