XTLS/Xray-core · error
Routing statistics not enabled.
Error message
Routing statistics not enabled.
What it means
SubscribeRoutingStats requires a stats channel for routing events; the server was constructed (or the app booted) without one, so streaming is refused. The channel is only created when routing stats are enabled in the policy/stats configuration path.
Source
Thrown at app/router/command/command.go:109
func (s *routingServer) TestRoute(ctx context.Context, request *TestRouteRequest) (*RoutingContext, error) {
if request.RoutingContext == nil {
return nil, errors.New("Invalid routing request.")
}
route, err := s.router.PickRoute(AsRoutingContext(request.RoutingContext))
if err != nil {
return nil, err
}
if request.PublishResult && s.routingStats != nil {
ctx, _ := context.WithTimeout(context.Background(), 4*time.Second)
s.routingStats.Publish(ctx, route)
}
return AsProtobufMessage(request.FieldSelectors)(route), nil
}
func (s *routingServer) SubscribeRoutingStats(request *SubscribeRoutingStatsRequest, stream RoutingService_SubscribeRoutingStatsServer) error {
if s.routingStats == nil {
return errors.New("Routing statistics not enabled.")
}
genMessage := AsProtobufMessage(request.FieldSelectors)
subscriber, err := stats.SubscribeRunnableChannel(s.routingStats)
if err != nil {
return err
}
defer stats.UnsubscribeClosableChannel(s.routingStats, subscriber)
for {
select {
case value, ok := <-subscriber:
if !ok {
return errors.New("Upstream closed the subscriber channel.")
}
route, ok := value.(routing.Route)
if !ok {
return errors.New("Upstream sent malformed statistics.")
}
err := stream.Send(genMessage(route))View on GitHub (pinned to 7d214f8b09)
Solutions
- Enable routing statistics in the instance (add stats + policy configuration) and restart
- Ensure the RoutingService is created through the normal app wiring so routingStats is injected
- If embedding, pass a non-nil stats.Channel to NewRoutingServer
Example fix
// before command.NewRoutingServer(router, nil) // SubscribeRoutingStats -> not enabled // after statsCh := statsChannelFromApp // obtained via features/stats command.NewRoutingServer(router, statsCh)
Defensive patterns
Strategy: validation
Validate before calling
// Check the feature before subscribing:
if statsFeature == nil || !statsFeature.Running() {
return fmt.Errorf("routing stats unavailable; enable stats in config")
} Prevention
- Enable the stats app and routing stats in config before exposing SubscribeRoutingStats
- Feature-detect at client startup and disable the stats UI tab when unavailable
- Pass a real stats.Channel when constructing the routing server in embedded builds
When it happens
Trigger: Streaming SubscribeRoutingStats when s.routingStats == nil: stats feature not registered or routing statistics not enabled in config.
Common situations: Calling SubscribeRoutingStats on an instance whose stats service is absent; policy level stats not enabled; NewRoutingServer called directly with nil routingStats in embedded setups.
Related errors
- unsupported router implementation
- Invalid routing request.
- Upstream closed the subscriber channel.
- Upstream sent malformed statistics.
- this rule has no effective fields
AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15).
Data as JSON: /api/errors/f84bbbff7dd00bf4.
Report an issue: GitHub.