XTLS/Xray-core · error
failed to dispatch request to ${destination}
Error message
failed to dispatch request to ${destination} What it means
The routing dispatcher refused to open an outbound link for the destination requested by the trojan client (dispatcher.Dispatch failed). Dispatch resolves the destination through routing rules and dials the first outbound; failure means no route matched, the outbound errored, or the destination is invalid/unreachable.
Source
Thrown at proxy/trojan/server.go:334
if err := task.Run(ctx, requestDone); err != nil {
return err
}
return nil
}
func (s *Server) handleConnection(ctx context.Context, sessionPolicy policy.Session,
destination net.Destination,
clientReader buf.Reader,
clientWriter buf.Writer, dispatcher routing.Dispatcher,
) error {
ctx, cancel := context.WithCancel(ctx)
timer := signal.CancelAfterInactivity(ctx, cancel, sessionPolicy.Timeouts.ConnectionIdle)
ctx = policy.ContextWithBufferPolicy(ctx, sessionPolicy.Buffer)
link, err := dispatcher.Dispatch(ctx, destination)
if err != nil {
return errors.New("failed to dispatch request to ", destination).Base(err)
}
requestDone := func() error {
defer timer.SetTimeout(sessionPolicy.Timeouts.DownlinkOnly)
if buf.Copy(clientReader, link.Writer, buf.UpdateActivity(timer)) != nil {
return errors.New("failed to transfer request").Base(err)
}
return nil
}
responseDone := func() error {
defer timer.SetTimeout(sessionPolicy.Timeouts.UplinkOnly)
if err := buf.Copy(link.Reader, clientWriter, buf.UpdateActivity(timer)); err != nil {
return errors.New("failed to write response").Base(err)
}
return nil
}View on GitHub (pinned to 7d214f8b09)
Solutions
- Check routing rules: does a rule with action 'block' or a bogus outboundTag match this destination
- Verify the outboundTag in rules exists in outbounds and that outbound can dial (test it directly)
- Look at the Base error in the log — it carries the dispatcher's own failure reason (e.g. 'failed to get outbound handler' or dial timeout)
- If DNS inside dispatch fails, fix the configured DNS servers or use domainStrategy ipResolve on the outbound
Example fix
// json: make sure the tag referenced by rules exists
"routing": {"rules": [{"type": "field", "ip": ["geoip:private"], "outboundTag": "direct"}]},
"outbounds": [{"tag": "direct", "protocol": "freedom"}] Defensive patterns
Strategy: validation
Validate before calling
// before dispatching, sanity-check the destination shape
func validDest(d net.Destination) bool {
return d.Port > 0 && d.Address != nil &&
(d.Network == net.Network_TCP || d.Network == net.Network_UDP)
} Try / catch
link, err := dispatcher.Dispatch(ctx, destination)
if err != nil {
errors.LogError(ctx, errors.New("failed to dispatch request to ", destination).Base(err))
return err // per-connection failure; do not crash the inbound
} Prevention
- Validate config at startup: every outboundTag in routing rules must exist in outbounds
- Add an explicit final direct/block rule so dispatch always has a valid target
- Test outbounds independently after credential or server changes
When it happens
Trigger: Routing rules send the destination to a tag that does not exist (balancer/strategy typo), the selected outbound fails to dial (freedom with blocked network, proxy outbound down), or the destination address is malformed (e.g. empty domain after client-side resolution).
Common situations: Config references an outbound tag removed in an edit; 'block' rule matched unintentionally; upstream proxy credentials expired; DNS failure inside dispatch.
Related errors
- XUDP new
- failed to dispatch request.
- failed to dispatch request
- connection closed
- balancing strategy returns empty tag
AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15).
Data as JSON: /api/errors/633b3abcdfd097ee.
Report an issue: GitHub.