{"record":{"id":"7bc0ad0fa7e32075","repo":"MHSanaei/3x-ui","slug":"xray-is-not-running-7bc0ad","errorCode":null,"errorMessage":"xray is not running","messagePattern":"xray is not running","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"info","filePath":"internal/xray/process.go","lineNumber":666,"sourceCode":"\tif runtime.GOOS == \"windows\" {\n\t\terrStr := strings.ToLower(err.Error())\n\t\tif strings.Contains(errStr, \"exit status 1\") {\n\t\t\tp.setExitErr(err)\n\t\t\treturn\n\t\t}\n\t}\n\n\tlogger.Error(\"Failure in running xray-core:\", err)\n\tp.setExitErr(err)\n\tif OnCrash != nil {\n\t\tOnCrash(err)\n\t}\n}\n\n// Stop terminates the running Xray process.\nfunc (p *process) Stop() error {\n\tif !p.IsRunning() {\n\t\treturn errors.New(\"xray is not running\")\n\t}\n\tp.intentionalStop.Store(true)\n\n\t// Snapshot cmd once, then run the blocking Signal/Kill/Wait on the local copy\n\t// without holding the lock.\n\tp.mu.RLock()\n\tcmd := p.cmd\n\tp.mu.RUnlock()\n\tif cmd == nil || cmd.Process == nil {\n\t\treturn errors.New(\"xray is not running\")\n\t}\n\n\t// Remove temporary config file used for test runs so main config is never touched\n\tif p.configPath != \"\" {\n\t\tif p.configPath != GetConfigPath() {\n\t\t\t// Check if file exists before removing\n\t\t\tif _, err := os.Stat(p.configPath); err == nil {\n\t\t\t\t_ = os.Remove(p.configPath)","sourceCodeStart":648,"sourceCodeEnd":684,"githubUrl":"https://github.com/MHSanaei/3x-ui/blob/ad32144c42455696ea9f14e12168beac3e25f5d2/internal/xray/process.go#L648-L684","documentation":"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.","triggerScenarios":"StopXray racing a core crash; stopping after someone already stopped; stopping a process object whose cmd was never started (fresh instance).","commonSituations":"Panel shutdown after xray crashed on bad config; double-stop sequences; orchestrating restarts where the crash handler already reaped the child.","solutions":["Treat as benign when the goal is 'make sure it is stopped' — that state already holds.","If a crash is suspected, read the xray log and the exit error recorded via setExitErr to find the root cause.","Serialize stop/start flows through XrayService's lock to avoid racing the crash-restart handler."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err := p.Stop(); err != nil {\n    if strings.Contains(err.Error(), \"xray is not running\") {\n        return nil // already stopped\n    }\n    return err\n}","preventionTips":["Treat stop as idempotent in all orchestration code.","If the core was expected alive, pull the exit error set by setExitErr / crash logs to find why it died first."],"tags":["xray","lifecycle","shutdown"],"backgroundTag":null,"analyzedSha":"ad32144c42455696ea9f14e12168beac3e25f5d2","analyzedAt":"2026-08-15T11:13:23.905Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}