{"record":{"id":"7e6431b6cd8984de","repo":"fatedier/frp","slug":"do-http-request-error-code-d","errorCode":null,"errorMessage":"do http request error code: %d","messagePattern":"do http request error code: (.+?)","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/plugin/server/http.go","lineNumber":107,"sourceCode":"\t}\n\tv := url.Values{}\n\tv.Set(\"version\", r.Version)\n\tv.Set(\"op\", r.Op)\n\treq, err := http.NewRequest(\"POST\", p.url+\"?\"+v.Encode(), bytes.NewReader(buf))\n\tif err != nil {\n\t\treturn err\n\t}\n\treq = req.WithContext(ctx)\n\treq.Header.Set(\"X-Frp-Reqid\", GetReqidFromContext(ctx))\n\treq.Header.Set(\"Content-Type\", \"application/json\")\n\tresp, err := p.client.Do(req)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer resp.Body.Close()\n\n\tif resp.StatusCode != http.StatusOK {\n\t\treturn fmt.Errorf(\"do http request error code: %d\", resp.StatusCode)\n\t}\n\tbuf, err = io.ReadAll(resp.Body)\n\tif err != nil {\n\t\treturn err\n\t}\n\treturn json.Unmarshal(buf, res)\n}\n","sourceCodeStart":89,"sourceCodeEnd":115,"githubUrl":"https://github.com/fatedier/frp/blob/6c8a8d0a97d03b44e9528d30b30c70cb9d61b405/pkg/plugin/server/http.go#L89-L115","documentation":"A server-side HTTP plugin returned a non-200 status code for an frps operation request (Login/NewUser/NewProxy/CloseProxy/Ping...). frps posts JSON to the plugin's HTTPAddr; any response other than http.StatusOK is rejected with this error, carrying the numeric status.","triggerScenarios":"frps configured with [[httpPlugins]], and the plugin endpoint returns 4xx/5xx — auth denial implemented as 403, plugin bug returning 500, wrong endpoint path returning 404, or a reverse proxy in front returning 502.","commonSituations":"Plugin deliberately rejects with non-200 instead of the expected 200+Reject pattern; plugin route not matching addr.path; plugin process down behind a gateway that answers 502/503; plugin framework returning 405 for a POST/GET method mismatch.","solutions":["Map the status code: 404/405 means the path or method in the plugin config is wrong; 401/403 means the plugin refused the request; 5xx means the plugin itself errored","Check the plugin service's own logs at the timestamp of the frps error","Ensure the plugin implements the frps HTTP plugin protocol: always answer 200 and use the Reject/RejectReason fields for denials","Verify [[httpPlugins]].addr points to the exact route handling the operation"],"exampleFix":"// before (plugin handler)\nfunc handler(w http.ResponseWriter, r *http.Request) {\n  if !allowed(r) {\n    w.WriteHeader(http.StatusForbidden) // frps turns this into 'error code: 403'\n    return\n  }\n}\n\n// after — always 200, express denial in content\nret := HandleResponse{Reject: true, RejectReason: \"not allowed\"}\nw.Header().Set(\"Content-Type\", \"application/json\")\nw.WriteHeader(http.StatusOK)\njson.NewEncoder(w).Encode(ret)","handlingStrategy":"try-catch","validationCode":"// Health-check the plugin endpoint at frps startup\nresp, err := http.Get(pluginAddr + \"/healthz\")\nif err != nil || resp.StatusCode != 200 {\n    return errors.New(\"http plugin not ready\")\n}","typeGuard":null,"tryCatchPattern":"if err := manager.Login(content); err != nil {\n    if strings.Contains(err.Error(), \"error code\") {\n        // plugin answered with non-200: log status and consult plugin logs\n        log.Errorf(\"http plugin rejected op with status: %v\", err)\n    }\n}","preventionTips":["Implement frp plugin protocol correctly: always 200, denials via reject/reject_reason","Add readiness checks for the plugin service before frps routes ops to it","Return actionable bodies from non-200 responses so debugging is possible"],"tags":["plugin","http","server","go"],"backgroundTag":null,"analyzedSha":"6c8a8d0a97d03b44e9528d30b30c70cb9d61b405","analyzedAt":"2026-08-15T06:53:27.215Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}