vaxilu/x-ui · info
xray is not running
Error message
xray is not running
What it means
process.Stop in xray/process.go returns this error when IsRunning() is false, meaning there is no live process whose cmd.Process can be killed. It prevents calling Kill() on a nil or exited process handle, which would otherwise panic or be meaningless. It is the low-level counterpart of the service-level StopXray guard.
Source
Thrown at xray/process.go:227
}
}()
go func() {
err := cmd.Run()
if err != nil {
p.exitErr = err
}
}()
p.refreshVersion()
p.refreshAPIPort()
return nil
}
func (p *process) Stop() error {
if !p.IsRunning() {
return errors.New("xray is not running")
}
return p.cmd.Process.Kill()
}
func (p *process) GetTraffic(reset bool) ([]*Traffic, error) {
if p.apiPort == 0 {
return nil, common.NewError("xray api port wrong:", p.apiPort)
}
conn, err := grpc.Dial(fmt.Sprintf("127.0.0.1:%v", p.apiPort), grpc.WithInsecure())
if err != nil {
return nil, err
}
defer conn.Close()
client := statsservice.NewStatsServiceClient(conn)
ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
defer cancel()
request := &statsservice.QueryStatsRequest{View on GitHub (pinned to 9c1be8c57a)
Solutions
- Check IsRunning() before calling Stop and treat already-stopped as success
- Use the service-level StopXray/RestartXray which handle the locking for you
- If xray should be running but isn't, check logs for why it exited and fix before restarting
Example fix
// before
if err := p.Stop(); err != nil {
logger.Error(err)
}
// after
if p.IsRunning() {
if err := p.Stop(); err != nil {
logger.Error(err)
}
} // already stopped — nothing to do Defensive patterns
Strategy: validation
Validate before calling
if !p.IsRunning() {
return nil // nothing to stop
}
return p.Stop() Try / catch
if err := p.Stop(); err != nil {
if err.Error() == "xray is not running" {
logger.Debug("already stopped")
return nil
}
return err
} Prevention
- Check IsRunning() before Kill/Stop
- Handle the race where the process exits between check and kill (recover from panic on Process.Kill)
- Use the higher-level StopXray which already guards this
- Monitor unexpected exits so stop calls arrive on live processes
When it happens
Trigger: Calling process.Stop() after xray already exited on its own (crash, config error), before Start() was ever called, or in a race where the process dies between IsRunning() and Kill().
Common situations: Panel stop/restart flows racing with a core crash; stopping during startup failure; scripts shutting down the panel while xray had already terminated.
Related errors
AI-assisted analysis of vaxilu/x-ui@9c1be8c57a (2026-09-02).
Data as JSON: /api/errors/c21d5009c6067c48.
Report an issue: GitHub.