{"record":{"id":"e037d064dc5a08f5","repo":"fatedier/frp","slug":"s-e037d0","errorCode":null,"errorMessage":"%s","messagePattern":"%s","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/plugin/server/manager.go","lineNumber":97,"sourceCode":"\n\tvar (\n\t\tres = &Response{\n\t\t\tReject:   false,\n\t\t\tUnchange: true,\n\t\t}\n\t\tretContent any\n\t\terr        error\n\t)\n\tctx, xl := newPluginRequestContext()\n\n\tfor _, p := range plugins {\n\t\tres, retContent, err = p.Handle(ctx, op, *content)\n\t\tif err != nil {\n\t\t\tlogPluginError(xl, p, op, err, logMode)\n\t\t\treturn nil, errors.New(\"send \" + op + \" request to plugin error\")\n\t\t}\n\t\tif res.Reject {\n\t\t\treturn nil, fmt.Errorf(\"%s\", res.RejectReason)\n\t\t}\n\t\tif !res.Unchange {\n\t\t\t// Preserve the existing Plugin contract: changed content must be *T.\n\t\t\t// Buggy Plugin implementations still panic here, by design.\n\t\t\tcontent = retContent.(*T)\n\t\t}\n\t}\n\treturn content, nil\n}\n\nfunc (m *Manager) Register(p Plugin) {\n\tif p.IsSupport(OpLogin) {\n\t\tm.loginPlugins = append(m.loginPlugins, p)\n\t}\n\tif p.IsSupport(OpNewProxy) {\n\t\tm.newProxyPlugins = append(m.newProxyPlugins, p)\n\t}\n\tif p.IsSupport(OpCloseProxy) {","sourceCodeStart":79,"sourceCodeEnd":115,"githubUrl":"https://github.com/fatedier/frp/blob/6c8a8d0a97d03b44e9528d30b30c70cb9d61b405/pkg/plugin/server/manager.go#L79-L115","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if _, err := manager.Login(content); err != nil {\n    // err.Error() is the plugin's reject_reason verbatim — surface it to the client/user\n    return err\n}","preventionTips":["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"],"tags":["plugin","server","authorization","go"],"backgroundTag":null,"analyzedSha":"6c8a8d0a97d03b44e9528d30b30c70cb9d61b405","analyzedAt":"2026-08-15T06:53:27.215Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}