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
- Include a full authority in the callback URL: scheme://host[:port]/path.
- Check the environment/config value feeding the host portion of the URL (e.g. PUBLIC_HOST is unset).
- 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
- Fail fast at config load if PUBLIC_HOST/base-URL env vars are empty
- Build URLs with url.URL struct fields instead of string concatenation
- Test webhook URL templates with empty-variable substitution
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
- push callback scheme %q not allowed (want http or https)
- push callback host %q: %w
- push callback host %q resolves to a blocked address %s
- ai model is nil
- ErrMissingTopic
AI-assisted analysis of micro/go-micro@24529f1404 (2026-09-01).
Data as JSON: /api/errors/8ea0353ad0405156.
Report an issue: GitHub.