fatedier/frp · error
%s
Error message
%s
What it means
A server plugin explicitly rejected an operation: the plugin returned res.Reject = true, and frps surfaces the plugin's own RejectReason string as the error. This is the protocol-correct way frps plugins deny Logins, NewProxy, NewUser, Ping, etc. — the message text comes entirely from the plugin, not from frp.
Source
Thrown at pkg/plugin/server/manager.go:97
var (
res = &Response{
Reject: false,
Unchange: true,
}
retContent any
err error
)
ctx, xl := newPluginRequestContext()
for _, p := range plugins {
res, retContent, err = p.Handle(ctx, op, *content)
if err != nil {
logPluginError(xl, p, op, err, logMode)
return nil, errors.New("send " + op + " request to plugin error")
}
if res.Reject {
return nil, fmt.Errorf("%s", res.RejectReason)
}
if !res.Unchange {
// Preserve the existing Plugin contract: changed content must be *T.
// Buggy Plugin implementations still panic here, by design.
content = retContent.(*T)
}
}
return content, nil
}
func (m *Manager) Register(p Plugin) {
if p.IsSupport(OpLogin) {
m.loginPlugins = append(m.loginPlugins, p)
}
if p.IsSupport(OpNewProxy) {
m.newProxyPlugins = append(m.newProxyPlugins, p)
}
if p.IsSupport(OpCloseProxy) {View on GitHub (pinned to 6c8a8d0a97)
Solutions
- The message body is the plugin's reject_reason — act on that text (it often states the policy violated)
- Fix the condition the plugin checks: correct token, allowed user, permitted proxy name/type
- If the rejection is unexpected, inspect the plugin's config/logs to see why its allow rule did not match
- To let this client through, adjust the plugin's ACL — not the frps auth config, since the plugin overrode it
Defensive patterns
Strategy: try-catch
Try / catch
if _, err := manager.Login(content); err != nil {
// err.Error() is the plugin's reject_reason verbatim — surface it to the client/user
return err
} Prevention
- Make plugin reject_reason strings actionable for end users
- Keep plugin ACL data (users, proxy allowlists) in sync with frps auth config
- Log op + reject_reason pairs to audit denials
When it happens
Trigger: An [[httpPlugins]] entry on frps handles an op (e.g. OpLogin) and its JSON response contains {"reject": true, "reject_reason": "..."} — the reason string becomes this error.
Common situations: Auth/ACL plugins denying a client login or proxy creation by policy; misconfigured plugin rejecting everything (e.g. cannot read its own ACL file); operations team using reject_reason as the user-facing denial message.
Related errors
- send ${op} request to plugin error
- do http request error code: %d
- send CloseProxy request to plugin errors: %s
- no route found
- router config conflict
AI-assisted analysis of fatedier/frp@6c8a8d0a97 (2026-08-15).
Data as JSON: /api/errors/e037d064dc5a08f5.
Report an issue: GitHub.