{"record":{"id":"b24ce1383dfdbeca","repo":"MHSanaei/3x-ui","slug":"http-d-from-remote-panel","errorCode":null,"errorMessage":"HTTP %d from remote panel","messagePattern":"HTTP (.+?) from remote panel","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/web/service/node.go","lineNumber":1152,"sourceCode":"\n\tclient, err := runtime.HTTPClientForNode(n, proxyURL)\n\tif err != nil {\n\t\tpatch.LastError = err.Error()\n\t\treturn patch, err\n\t}\n\n\tstart := time.Now()\n\tresp, err := client.Do(req)\n\tif err != nil {\n\t\tpatch.LastError = err.Error()\n\t\treturn patch, err\n\t}\n\tdefer resp.Body.Close()\n\tpatch.LatencyMs = int(time.Since(start) / time.Millisecond)\n\n\tif resp.StatusCode != http.StatusOK {\n\t\tpatch.LastError = fmt.Sprintf(\"HTTP %d from remote panel\", resp.StatusCode)\n\t\treturn patch, errors.New(patch.LastError)\n\t}\n\n\tvar envelope struct {\n\t\tSuccess bool   `json:\"success\"`\n\t\tMsg     string `json:\"msg\"`\n\t\tObj     *struct {\n\t\t\tCpuPct float64 `json:\"cpu\"`\n\t\t\tMem    struct {\n\t\t\t\tCurrent uint64 `json:\"current\"`\n\t\t\t\tTotal   uint64 `json:\"total\"`\n\t\t\t} `json:\"mem\"`\n\t\t\tXray struct {\n\t\t\t\tVersion  string `json:\"version\"`\n\t\t\t\tState    string `json:\"state\"`\n\t\t\t\tErrorMsg string `json:\"errorMsg\"`\n\t\t\t} `json:\"xray\"`\n\t\t\tPanelVersion string `json:\"panelVersion\"`\n\t\t\tPanelGuid    string `json:\"panelGuid\"`","sourceCodeStart":1134,"sourceCodeEnd":1170,"githubUrl":"https://github.com/MHSanaei/3x-ui/blob/ad32144c42455696ea9f14e12168beac3e25f5d2/internal/web/service/node.go#L1134-L1170","documentation":"The node status probe reached the remote panel but got a non-200 HTTP status, so the health check fails with 'HTTP %d from remote panel' recorded in patch.LastError. The request itself succeeded (LatencyMs is set), so this is the remote speaking HTTP but rejecting the call — typically 401 (bad/missing API token), 404 (wrong base path), or 5xx (remote panel unhealthy).","triggerScenarios":"Node's API token rotated on the remote but not updated locally → 401; wrong BasePath so the status URL misses the panel router → 404; remote panel restarting or erroring → 502/500; TLS scheme mismatch (https to an http port can also surface as a proxy error).","commonSituations":"Multi-node deployments after credential rotation; base-path misconfiguration behind reverse proxies; remote node temporarily down.","solutions":["Match the reported code: 401 → re-enter the node's API token; 404 → fix BasePath; 5xx → inspect the remote panel's own logs","curl the URL by hand from the manager node to see the exact status and body","Verify scheme matches the actual listener (http vs https) and the port is the panel port, not the xray inbound port"],"exampleFix":"# before\nnode: { address: 'sub1.example.com', port: 443, scheme: 'https', basePath: '/' }\n# (HTTP 404 from remote panel)\n\n# after\nnode: { address: 'sub1.example.com', port: 443, scheme: 'https', basePath: '/xui' }\n# then: curl -H 'Authorization: Bearer <token>' https://sub1.example.com/xui/panel/api/server/status","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"resp, err := probe(ctx, node)\nif err != nil && strings.Contains(err.Error(), \"HTTP \") {\n    // 5xx from a restarting remote may clear: retry with backoff once\n    time.Sleep(2 * time.Second)\n    resp, err = probe(ctx, node)\n}","preventionTips":["Keep the node's API token, base path, scheme and port in sync with the remote panel","Verify with curl from the manager node whenever a node is added","Distinguish 401/404 (config) from 5xx (remote health) before changing anything"],"tags":["node","network","http","health-check"],"backgroundTag":null,"analyzedSha":"ad32144c42455696ea9f14e12168beac3e25f5d2","analyzedAt":"2026-08-15T11:13:23.905Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}