XTLS/Xray-core · error
empty worker list
Error message
empty worker list
What it means
StaticMuxPicker (the portal's pool of bridge-backed mux workers) has zero registered workers when PickAvailable is called. Every tunneled connection must ride an existing worker; with an empty list there is no bridge connected at all, so picking fails. Typically returned up through the outbound dispatcher when traffic is routed to the portal tag but no bridge has established its tunnel.
Source
Thrown at app/reverse/portal.go:180
activeWorkers = append(activeWorkers, w)
} else {
w.timer.SetTimeout(0)
}
}
if len(activeWorkers) != len(p.workers) {
p.workers = activeWorkers
}
return nil
}
func (p *StaticMuxPicker) PickAvailable() (*mux.ClientWorker, error) {
p.access.Lock()
defer p.access.Unlock()
if len(p.workers) == 0 {
return nil, errors.New("empty worker list")
}
var minIdx int = -1
var minConn uint32 = 9999
for i, w := range p.workers {
if w.draining {
continue
}
if w.IsFull() {
continue
}
if w.client.ActiveConnections() < minConn {
minConn = w.client.ActiveConnections()
minIdx = i
}
}
if minIdx == -1 {View on GitHub (pinned to 7d214f8b09)
Solutions
- Verify the bridge side is running and its outbound points at the portal's address/tag; check portal logs for accepted bridge connections.
- Ensure routing rules send traffic to the portal tag only when bridges exist, or add a fallbackTag/observability so the failure is visible.
- If workers keep disappearing, debug why bridge connections drop (see errors 91/92) — this error is usually the symptom, not the cause.
Defensive patterns
Strategy: fallback
Validate before calling
// Before routing traffic to the portal tag, confirm bridges are connected
if picker.Len() == 0 { // expose worker count from StaticMuxPicker
return routeDirectOrReject(ctx, link) // no bridge tunnel exists yet
} Type guard
func portalHasWorkers(picker reverse.WorkerCounter) bool { return picker.Len() > 0 } Try / catch
if err := dispatch(ctx, link); err != nil {
if strings.Contains(err.Error(), "empty worker list") {
return routeViaFallbackTag(ctx, link) // or queue briefly until first bridge registers
}
return err
} Prevention
- Start bridges before routing production traffic to the portal tag
- Monitor bridge connection state and alert when worker count stays zero
- Add a routing fallback (different balancer/outbound) for portal-tag rules
When it happens
Trigger: Traffic dispatched to the portal's outbound tag while p.workers == 0 — i.e. before any bridge connected, or after all bridge workers were reaped (closed/drained and removed by the picker's cleanup that filters activeWorkers).
Common situations: Portal side up but bridge side down/offline (reverse client never connected, or lost network); bridge connects to the wrong portal address; startup ordering where routing sends traffic before the first bridge tunnel arrives; long outages where the last worker was cleaned up.
Related errors
- failed to create mux client worker
- failed to create portal worker
- no mux client worker available
- unable to dispatch control connection
- failed to process mux outbound traffic
AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15).
Data as JSON: /api/errors/d3290cb588df457b.
Report an issue: GitHub.