{"record":{"id":"245e1d94661fe336","repo":"fatedier/frp","slug":"send-closeproxy-request-to-plugin-errors-s","errorCode":null,"errorMessage":"send CloseProxy request to plugin errors: %s","messagePattern":"send CloseProxy request to plugin errors: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"pkg/plugin/server/manager.go","lineNumber":154,"sourceCode":"\nfunc (m *Manager) CloseProxy(content *CloseProxyContent) error {\n\tif len(m.closeProxyPlugins) == 0 {\n\t\treturn nil\n\t}\n\n\terrs := make([]string, 0)\n\tctx, xl := newPluginRequestContext()\n\n\tfor _, p := range m.closeProxyPlugins {\n\t\t_, _, err := p.Handle(ctx, OpCloseProxy, *content)\n\t\tif err != nil {\n\t\t\txl.Warnf(\"send CloseProxy request to plugin [%s] error: %v\", p.Name(), err)\n\t\t\terrs = append(errs, fmt.Sprintf(\"[%s]: %v\", p.Name(), err))\n\t\t}\n\t}\n\n\tif len(errs) > 0 {\n\t\treturn fmt.Errorf(\"send CloseProxy request to plugin errors: %s\", strings.Join(errs, \"; \"))\n\t}\n\treturn nil\n}\n\nfunc (m *Manager) Ping(content *PingContent) (*PingContent, error) {\n\treturn handleMutableContent(m.pingPlugins, OpPing, content, pluginErrorLogWarn)\n}\n\nfunc (m *Manager) NewWorkConn(content *NewWorkConnContent) (*NewWorkConnContent, error) {\n\treturn handleMutableContent(m.newWorkConnPlugins, OpNewWorkConn, content, pluginErrorLogWarn)\n}\n\nfunc (m *Manager) NewUserConn(content *NewUserConnContent) (*NewUserConnContent, error) {\n\t// Preserve the pre-refactor log level for NewUserConn plugin errors.\n\treturn handleMutableContent(m.newUserConnPlugins, OpNewUserConn, content, pluginErrorLogInfo)\n}\n","sourceCodeStart":136,"sourceCodeEnd":171,"githubUrl":"https://github.com/fatedier/frp/blob/6c8a8d0a97d03b44e9528d30b30c70cb9d61b405/pkg/plugin/server/manager.go#L136-L171","documentation":"One or more CloseProxy-aware server plugins failed to handle the OpCloseProxy request (transport error or non-200 from p.Handle). frps collects every failing plugin as \"[pluginName]: err\", joined with '; '. Unlike rejection, this is a plugin invocation failure during proxy teardown.","triggerScenarios":"Manager.CloseProxy iterating m.closeProxyPlugins where at least one p.Handle returns err — plugin endpoint unreachable, timed out, or returned non-200 while frps was closing a proxy.","commonSituations":"Plugin service restarted or down when proxies close; plugin only partially implements operations and errors on CloseProxy; network blip between frps and the plugin.","solutions":["Identify the failing plugin from the [name]: err entries in the message","Check whether the plugin process is alive and its endpoint reachable from frps","Make the plugin return 200 withunchanged for CloseProxy if it does not track proxy state","Since this occurs during teardown, assess whether the error has real impact; failing closes usually just leak plugin-side bookkeeping"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err := manager.CloseProxy(content); err != nil {\n    // teardown best-effort: log, don't fail the close path\n    log.Warnf(\"close proxy plugin errors (non-fatal): %v\", err)\n}","preventionTips":["Treat CloseProxy plugin errors as warnings; don't abort proxy teardown on them","Keep plugin services highly available or make them tolerate unavailability during close","Implement all ops in the plugin, returning unchange for ones you don't track"],"tags":["plugin","server","lifecycle","go"],"backgroundTag":null,"analyzedSha":"6c8a8d0a97d03b44e9528d30b30c70cb9d61b405","analyzedAt":"2026-08-15T06:53:27.215Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}