{"record":{"id":"606383080a9323e0","repo":"MHSanaei/3x-ui","slug":"failed-to-start-test-xray-instance-w","errorCode":null,"errorMessage":"Failed to start test xray instance: %w","messagePattern":"Failed to start test xray instance: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/web/service/outbound/probe_http.go","lineNumber":306,"sourceCode":"\t\treturn false, fmt.Errorf(\"Failed to create test config path: %w\", err)\n\t}\n\tdefer os.Remove(configPath)\n\n\tproc := newBatchProcess(cfg, configPath)\n\tdefer func() {\n\t\tif proc.IsRunning() {\n\t\t\t_ = proc.Stop()\n\t\t}\n\t}()\n\n\t// Free the reserved ports just before xray binds them; the window is\n\t// milliseconds, and a lost race makes xray exit fast, which surfaces\n\t// below and triggers the per-item retry with fresh ports.\n\trelease()\n\tif err := proc.Start(); err != nil {\n\t\tif errors.Is(err, fs.ErrNotExist) {\n\t\t\t// Binary missing — per-item retries would all fail the same way.\n\t\t\treturn false, fmt.Errorf(\"Failed to start test xray instance: %w\", err)\n\t\t}\n\t\treturn true, fmt.Errorf(\"Failed to start test xray instance: %w\", err)\n\t}\n\n\tif err := waitForPortsReady(proc, ports, batchPortsReadyTimeout); err != nil {\n\t\treturn err.exited, err\n\t}\n\n\tsem := make(chan struct{}, httpProbeConcurrency)\n\tvar wg sync.WaitGroup\n\tfor i := range items {\n\t\twg.Add(1)\n\t\tgo func(it *httpBatchItem, port int) {\n\t\t\tdefer wg.Done()\n\t\t\tsem <- struct{}{}\n\t\t\tdefer func() { <-sem }()\n\t\t\tprobeThroughSocks(port, testURL, httpProbeTimeout, realDelay, it.result)\n\t\t}(items[i], ports[i])","sourceCodeStart":288,"sourceCodeEnd":324,"githubUrl":"https://github.com/MHSanaei/3x-ui/blob/ad32144c42455696ea9f14e12168beac3e25f5d2/internal/web/service/outbound/probe_http.go#L288-L324","documentation":"proc.Start() failed and errors.Is(err, fs.ErrNotExist) matched, meaning the xray binary itself was not found at the expected path. The code marks it non-retryable (retryPerItem=false) because every per-item retry would hit the same missing binary. This is the outbound HTTP probe's dedicated 'xray not installed / wrong path' signal.","triggerScenarios":"Clicking 'test' on outbounds when the managed xray binary is absent — fresh install where the download step failed, XUI_BIN_FOLDER misconfigured, or the binary was deleted/renamed out from under the panel.","commonSituations":"Panel installed without xray asset download (offline install script); custom bin folder pointing to an empty directory; binary removed by an antivirus or a failed update.","solutions":["Verify the xray binary exists in the bin folder (ls <bin folder>) and reinstall it from the panel's xray version settings","Fix XUI_BIN_FOLDER so it points at the directory that actually contains xray","Check panel startup logs for an earlier xray download/update failure"],"exampleFix":"# before\nls /usr/local/x-ui/bin/   # empty -> probe fails with fs.ErrNotExist\n\n# after\n# reinstall/update xray via panel (Settings -> Xray version) or:\ncd /usr/local/x-ui/bin && wget https://github.com/XTLS/Xray-core/releases/download/vX.Y.Z/xray-linux-amd64 ... && chmod +x xray","handlingStrategy":"validation","validationCode":"if _, err := os.Stat(filepath.Join(config.GetBinFolderPath(), \"xray\")); errors.Is(err, fs.ErrNotExist) {\n    return errors.New(\"xray binary missing; install it before testing outbounds\")\n}","typeGuard":null,"tryCatchPattern":"_, err := runHTTPProbeBatch(items, all, url, true)\nif err != nil && errors.Is(err, fs.ErrNotExist) {\n    // the %w chain preserves ErrNotExist: prompt user to install/update xray\n}","preventionTips":["Verify xray presence at startup and expose its status in the UI","Re-download xray from panel settings after manual folder changes"],"tags":["xray","binary","filesystem","outbounds","environment"],"backgroundTag":null,"analyzedSha":"ad32144c42455696ea9f14e12168beac3e25f5d2","analyzedAt":"2026-08-15T11:13:23.905Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}