XTLS/Xray-core · error · errors.Error
failed to dispatch request
Error message
failed to dispatch request
What it means
After the dokodemo inbound has built reader/writer and a valid destination, it hands the link to the dispatcher via DispatchLink. If the dispatcher rejects the dispatch, the error is wrapped here. Causes are structural: missing default outbound, no matching routing outcome, or dispatcher-level context/inbound failures — the specific reason is chained in Base(err).
Source
Thrown at proxy/dokodemo/dokodemo.go:199
if d.sockopt != nil {
mark = int(d.sockopt.Mark)
}
pConn, err := FakeUDP(addr, mark)
if err != nil {
return err
}
writer = NewPacketWriter(pConn, &dest, mark, back)
defer writer.(*PacketWriter).Close() // close fake UDP conns
}
}
if err := dispatcher.DispatchLink(
ctx, dest, &transport.Link{
Reader: reader,
Writer: writer,
},
); err != nil {
return errors.New("failed to dispatch request").Base(err)
}
return nil // Unlike Dispatch(), DispatchLink() will not return until the outbound finishes Process()
}
func NewPacketWriter(conn net.PacketConn, d *net.Destination, mark int, back *net.UDPAddr) buf.Writer {
writer := &PacketWriter{
conn: conn,
conns: make(map[net.Destination]net.PacketConn),
mark: mark,
back: back,
}
writer.conns[*d] = conn
return writer
}
type PacketWriter struct {
conn net.PacketConn
conns map[net.Destination]net.PacketConnView on GitHub (pinned to 7d214f8b09)
Solutions
- Read the chained Base(err) to see which outbound/rule failed
- Ensure every outboundTag in routing rules matches an existing outbound tag
- Keep a valid first outbound (e.g. freedom or blackhole) as the default
- Re-run the boot after fixes to confirm the dispatcher accepts the link
Example fix
// before: rule points at removed outbound
{"routing":{"rules":[{"type":"field","ip":["geoip:private"],"outboundTag":"old-block"}]}}
// after
{"routing":{"rules":[{"type":"field","ip":["geoip:private"],"outboundTag":"block"}]},
"outbounds":[{"protocol":"blackhole","tag":"block"}]} Defensive patterns
Strategy: validation
Validate before calling
// verify every routing rule's outboundTag exists before boot
tags := map[string]bool{}
for _, o := range config.Outbounds { tags[o.Tag] = true }
for _, r := range config.Routing.Rules { if !tags[r.OutboundTag] { return fmt.Errorf("dangling outboundTag %s", r.OutboundTag) } } Try / catch
if err := d.dispatch(ctx, dest, link); err != nil {
if strings.Contains(err.Error(), "failed to dispatch request") { reportRoutingIntegrity(err); return err }
return err
} Prevention
- Lint routing rules against outbound tags in CI
- Always keep a valid default (first) outbound
- Dry-run boot in staging after editing routing or outbounds
When it happens
Trigger: DispatchLink returning an error: config with no usable outbound for the resolved tag, routing rule referencing a nonexistent outboundTag, or dispatcher failing to create the outbound handler (which can itself stem from outbound Init errors).
Common situations: Renaming/removing an outbound but leaving a routing rule pointing at the old tag; configs where the first outbound is not a valid default; handler-level init failures inside the chained outbound.
Related errors
- balancing strategy returns empty tag
- unable to select outbounds
- unsupported GetPrincipleTarget
- cannot find tag
- invalid portMap: {}
AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15).
Data as JSON: /api/errors/a8985a44a8557547.
Report an issue: GitHub.