MHSanaei/3x-ui · warning

xray is not running

Error message

xray is not running

What it means

GetXrayTraffic asks the running Xray core for live traffic counters over its gRPC API; it first resolves the current process and returns this error when currentXrayProcess() is nil or IsRunning() is false. It is a guard for 'no live core to query', not a gRPC failure. Common during startup, after a crash, or after a manual stop.

Source

Thrown at internal/web/service/xray.go:876

	}

	if !changed {
		return routerCfg
	}

	parsed["rules"] = activeRules
	out, err := json.Marshal(parsed)
	if err != nil {
		return routerCfg
	}
	return out
}

// GetXrayTraffic fetches the current traffic statistics from the running Xray process.
func (s *XrayService) GetXrayTraffic() ([]*xray.Traffic, []*xray.ClientTraffic, error) {
	process := currentXrayProcess()
	if process == nil || !process.IsRunning() {
		err := errors.New("xray is not running")
		logger.Debug("Attempted to fetch Xray traffic, but Xray is not running:", err)
		return nil, nil, err
	}
	apiPort := process.GetAPIPort()
	if err := s.xrayAPI.Init(apiPort); err != nil {
		logger.Debug("Failed to initialize Xray API:", err)
		return nil, nil, err
	}
	defer s.xrayAPI.Close()

	traffic, clientTraffic, err := s.xrayAPI.GetTraffic()
	if err != nil {
		logger.Debug("Failed to fetch Xray traffic:", err)
		return nil, nil, err
	}
	return traffic, clientTraffic, nil
}

View on GitHub (pinned to ad32144c42)

Solutions

  1. Check whether xray is expected to run at all (manually stopped / sub-node) — if so, ignore the error.
  2. Inspect Xray log (log folder per XUI_LOG_FOLDER) and the crash event for why the core exited; fix config and restart.
  3. Retry after the startup/restart window: poll IsRunning before retrying the traffic fetch.
Defensive patterns

Strategy: validation

Validate before calling

traffic, clientTraffic, err := xrayService.GetXrayTraffic()
if err != nil && strings.Contains(err.Error(), "xray is not running") {
    // core is down: skip this poll instead of surfacing an error
    return nil
}

Try / catch

if _, _, err := xrayService.GetXrayTraffic(); err != nil {
    if strings.Contains(err.Error(), "xray is not running") {
        log.Debug("skipping traffic poll: core down")
        return
    }
    return err
}

Prevention

When it happens

Trigger: Calling XrayService.GetXrayTraffic (panel dashboard traffic refresh) before the first StartXray completes, after StopXray, or after the xray-core child process exited/crashed and the crash handler has not yet restarted it.

Common situations: Dashboard opened right after panel boot; xray-core crashed on a bad config (check the xray.crash eventbus event and xray logs); running on a sub-node where the local core is intentionally stopped.

Related errors


AI-assisted analysis of MHSanaei/3x-ui@ad32144c42 (2026-08-15). Data as JSON: /api/errors/88e8bd468521df6d. Report an issue: GitHub.