XTLS/Xray-core · error
failed to resolve ip for target ${domain}
Error message
failed to resolve ip for target ${domain} What it means
Thrown while dispatching an outbound connection whose target is a domain: the handler tries to pre-resolve the domain to an IP because the sender's domainStrategy (TargetStrategy) demands it, and internet.LookupForIP fails. The error is first logged at info level; it becomes fatal for the connection only when the strategy has ForceIP() set (e.g. domainStrategy forceIP), in which case the error is submitted to the originator and the link is interrupted. Without ForceIP, resolution failure is tolerated and the domain is passed through unresolved.
Source
Thrown at app/proxyman/outbound/handler.go:194
func (h *Handler) Tag() string {
return h.tag
}
// Dispatch implements proxy.Outbound.Dispatch.
func (h *Handler) Dispatch(ctx context.Context, link *transport.Link) {
outbounds := session.OutboundsFromContext(ctx)
ob := outbounds[len(outbounds)-1]
content := session.ContentFromContext(ctx)
if h.senderSettings != nil && h.senderSettings.TargetStrategy.HasStrategy() && ob.Target.Address.Family().IsDomain() && (content == nil || !content.SkipDNSResolve) {
strategy := h.senderSettings.TargetStrategy
if ob.Target.Network == net.Network_UDP && ob.OriginalTarget.Address != nil {
strategy = strategy.GetDynamicStrategy(ob.OriginalTarget.Address.Family())
}
ips, err := internet.LookupForIP(ob.Target.Address.Domain(), strategy, nil)
if err != nil {
errors.LogInfoInner(ctx, err, "failed to resolve ip for target ", ob.Target.Address.Domain())
if h.senderSettings.TargetStrategy.ForceIP() {
err := errors.New("failed to resolve ip for target ", ob.Target.Address.Domain()).Base(err)
session.SubmitOutboundErrorToOriginator(ctx, err)
common.Interrupt(link.Writer)
common.Interrupt(link.Reader)
return
}
} else {
unchangedDomain := ob.Target.Address.Domain()
ob.Target.Address = net.IPAddress(ips[dice.Roll(len(ips))])
errors.LogInfo(ctx, "target: ", unchangedDomain, " resolved to: ", ob.Target.Address.String())
}
}
if ob.Target.Network == net.Network_UDP && ob.OriginalTarget.Address != nil && ob.OriginalTarget.Address != ob.Target.Address {
link.Reader = &buf.EndpointOverrideReader{Reader: link.Reader, Dest: ob.Target.Address, OriginalDest: ob.OriginalTarget.Address}
link.Writer = &buf.EndpointOverrideWriter{Writer: link.Writer, Dest: ob.Target.Address, OriginalDest: ob.OriginalTarget.Address}
}
if h.mux != nil {
test := func(err error) {View on GitHub (pinned to 7d214f8b09)
Solutions
- Check DNS connectivity and config: verify the configured nameservers respond (e.g. dig @server domain) and that the strategy's address family (IPv4/IPv6) actually has records for the domain.
- If the target domain is only resolvable remotely or resolution is unnecessary, relax domainStrategy from forceIP/forceIPv4/forceIPv6 to useIP or asis so failure is non-fatal.
- Set SkipDNSResolve on the inbound's sniffing/content when the client already supplies addresses or resolution should be deferred to the remote server.
- Fix or exclude the offending domain: correct typos, add a hosts entry for internal domains, or route the domain to an outbound whose remote side resolves it.
Example fix
// before (json config)
"outbounds": [{ "tag": "proxy", "protocol": "vmess",
"settings": { "vnext": [ /* ... */ ] },
"streamSettings": { ... } }]
// with policy forcing resolution failure to be fatal via forceIP in dns/sender settings
// after: allow domain pass-through when local resolution fails
"outbounds": [{ "tag": "proxy", "protocol": "vmess",
"settings": { "vnext": [ /* ... */ ] },
"streamSettings": { "sockopt": { "domainStrategy": "AsIs" } } }]
// or set "skipDNSResolve" in inbound sniffing options so pre-dispatch lookup is skipped Defensive patterns
Strategy: fallback
Validate before calling
// Pre-flight the exact resolution the handler will attempt
strategy := senderSettings.TargetStrategy // e.g. dns.IPOption{IPv4Enable:true}
if strategy.HasStrategy() && targetAddr.Family().IsDomain() {
ips, err := internet.LookupForIP(targetAddr.Domain(), strategy, nil)
if err != nil && strategy.ForceIP() {
// dispatch would be fatal: divert to another outbound or fail fast with context
return fmt.Errorf("pre-check: target %s unresolvable under forceIP", targetAddr.Domain())
}
} Type guard
func resolvesUnderStrategy(domain string, s dns.IPOption) bool {
if !s.HasStrategy() { return true }
ips, err := internet.LookupForIP(domain, s, nil)
return err == nil && len(ips) > 0
} Try / catch
// Dispatch-side: tolerate and reroute rather than propagate
if err := handler.Dispatch(ctx, link); err != nil && strings.Contains(err.Error(), "failed to resolve ip for target") {
if fb := fallbackHandlerFor(ctx); fb != nil { return fb.Dispatch(ctx, link) }
return err
} Prevention
- Health-check DNS servers in config before relying on forceIP strategies
- Use UseIP instead of ForceIP when domains may only be resolvable remotely
- Set skipDNSResolve on inbounds where pre-resolution is unnecessary
- Monitor for 'failed to resolve ip' info logs as an early DNS degradation signal
When it happens
Trigger: Calling Dispatch on an outbound handler whose senderSettings.TargetStrategy.HasStrategy() is true, the latest session outbound target is a domain (Family().IsDomain()), and content is nil or content.SkipDNSResolve is false, while the configured DNS server fails or times out on internet.LookupForIP(domain, strategy, nil). Only fatal when TargetStrategy.ForceIP() returns true (forceIP / ForceIP-style strategies); for UDP with an OriginalTarget, the dynamic strategy derived from GetDynamicStrategy is used instead.
Common situations: DNS server in config unreachable or black-holed (blocked port 53, doh endpoint down), a forceIP domainStrategy combined with a domain that has no A/AAAA records (e.g. a typo or an internal .local name), IPv6-only strategy (UseIPv6/forceIPv6) on a host with no IPv6 records/resolved routes, or sniffed domains the local resolver refuses. Also seen when skipDNSResolve is not set on inbounds that carry already-resolved content.
Related errors
- cannot dial remote address
- cannot finish connection
- failed to process mux outbound traffic
- failed to process outbound traffic
- failed to get outbound handler with tag: ${tag}
AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15).
Data as JSON: /api/errors/634dee52f2985983.
Report an issue: GitHub.