MHSanaei/3x-ui · info

xray is not running

Error message

xray is not running

What it means

process.Stop() first checks IsRunning(); if the core is not alive it returns this error instead of signaling. It means by the time Stop ran, the child had already exited (crash or external kill) or was never started. Nothing was signaled — the caller must decide whether that matters.

Source

Thrown at internal/xray/process.go:666

	if runtime.GOOS == "windows" {
		errStr := strings.ToLower(err.Error())
		if strings.Contains(errStr, "exit status 1") {
			p.setExitErr(err)
			return
		}
	}

	logger.Error("Failure in running xray-core:", err)
	p.setExitErr(err)
	if OnCrash != nil {
		OnCrash(err)
	}
}

// Stop terminates the running Xray process.
func (p *process) Stop() error {
	if !p.IsRunning() {
		return errors.New("xray is not running")
	}
	p.intentionalStop.Store(true)

	// Snapshot cmd once, then run the blocking Signal/Kill/Wait on the local copy
	// without holding the lock.
	p.mu.RLock()
	cmd := p.cmd
	p.mu.RUnlock()
	if cmd == nil || cmd.Process == nil {
		return errors.New("xray is not running")
	}

	// Remove temporary config file used for test runs so main config is never touched
	if p.configPath != "" {
		if p.configPath != GetConfigPath() {
			// Check if file exists before removing
			if _, err := os.Stat(p.configPath); err == nil {
				_ = os.Remove(p.configPath)

View on GitHub (pinned to ad32144c42)

Solutions

  1. Treat as benign when the goal is 'make sure it is stopped' — that state already holds.
  2. If a crash is suspected, read the xray log and the exit error recorded via setExitErr to find the root cause.
  3. Serialize stop/start flows through XrayService's lock to avoid racing the crash-restart handler.
Defensive patterns

Strategy: try-catch

Try / catch

if err := p.Stop(); err != nil {
    if strings.Contains(err.Error(), "xray is not running") {
        return nil // already stopped
    }
    return err
}

Prevention

When it happens

Trigger: StopXray racing a core crash; stopping after someone already stopped; stopping a process object whose cmd was never started (fresh instance).

Common situations: Panel shutdown after xray crashed on bad config; double-stop sequences; orchestrating restarts where the crash handler already reaped the child.

Related errors


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