fatedier/frp · error

do http request error code: %d

Error message

do http request error code: %d

What it means

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.

Source

Thrown at pkg/plugin/server/http.go:107

	}
	v := url.Values{}
	v.Set("version", r.Version)
	v.Set("op", r.Op)
	req, err := http.NewRequest("POST", p.url+"?"+v.Encode(), bytes.NewReader(buf))
	if err != nil {
		return err
	}
	req = req.WithContext(ctx)
	req.Header.Set("X-Frp-Reqid", GetReqidFromContext(ctx))
	req.Header.Set("Content-Type", "application/json")
	resp, err := p.client.Do(req)
	if err != nil {
		return err
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		return fmt.Errorf("do http request error code: %d", resp.StatusCode)
	}
	buf, err = io.ReadAll(resp.Body)
	if err != nil {
		return err
	}
	return json.Unmarshal(buf, res)
}

View on GitHub (pinned to 6c8a8d0a97)

Solutions

  1. 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
  2. Check the plugin service's own logs at the timestamp of the frps error
  3. Ensure the plugin implements the frps HTTP plugin protocol: always answer 200 and use the Reject/RejectReason fields for denials
  4. Verify [[httpPlugins]].addr points to the exact route handling the operation

Example fix

// before (plugin handler)
func handler(w http.ResponseWriter, r *http.Request) {
  if !allowed(r) {
    w.WriteHeader(http.StatusForbidden) // frps turns this into 'error code: 403'
    return
  }
}

// after — always 200, express denial in content
ret := HandleResponse{Reject: true, RejectReason: "not allowed"}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(ret)
Defensive patterns

Strategy: try-catch

Validate before calling

// Health-check the plugin endpoint at frps startup
resp, err := http.Get(pluginAddr + "/healthz")
if err != nil || resp.StatusCode != 200 {
    return errors.New("http plugin not ready")
}

Try / catch

if err := manager.Login(content); err != nil {
    if strings.Contains(err.Error(), "error code") {
        // plugin answered with non-200: log status and consult plugin logs
        log.Errorf("http plugin rejected op with status: %v", err)
    }
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of fatedier/frp@6c8a8d0a97 (2026-08-15). Data as JSON: /api/errors/7e6431b6cd8984de. Report an issue: GitHub.