fatedier/frp · warning

send CloseProxy request to plugin errors: %s

Error message

send CloseProxy request to plugin errors: %s

What it means

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.

Source

Thrown at pkg/plugin/server/manager.go:154

func (m *Manager) CloseProxy(content *CloseProxyContent) error {
	if len(m.closeProxyPlugins) == 0 {
		return nil
	}

	errs := make([]string, 0)
	ctx, xl := newPluginRequestContext()

	for _, p := range m.closeProxyPlugins {
		_, _, err := p.Handle(ctx, OpCloseProxy, *content)
		if err != nil {
			xl.Warnf("send CloseProxy request to plugin [%s] error: %v", p.Name(), err)
			errs = append(errs, fmt.Sprintf("[%s]: %v", p.Name(), err))
		}
	}

	if len(errs) > 0 {
		return fmt.Errorf("send CloseProxy request to plugin errors: %s", strings.Join(errs, "; "))
	}
	return nil
}

func (m *Manager) Ping(content *PingContent) (*PingContent, error) {
	return handleMutableContent(m.pingPlugins, OpPing, content, pluginErrorLogWarn)
}

func (m *Manager) NewWorkConn(content *NewWorkConnContent) (*NewWorkConnContent, error) {
	return handleMutableContent(m.newWorkConnPlugins, OpNewWorkConn, content, pluginErrorLogWarn)
}

func (m *Manager) NewUserConn(content *NewUserConnContent) (*NewUserConnContent, error) {
	// Preserve the pre-refactor log level for NewUserConn plugin errors.
	return handleMutableContent(m.newUserConnPlugins, OpNewUserConn, content, pluginErrorLogInfo)
}

View on GitHub (pinned to 6c8a8d0a97)

Solutions

  1. Identify the failing plugin from the [name]: err entries in the message
  2. Check whether the plugin process is alive and its endpoint reachable from frps
  3. Make the plugin return 200 withunchanged for CloseProxy if it does not track proxy state
  4. Since this occurs during teardown, assess whether the error has real impact; failing closes usually just leak plugin-side bookkeeping
Defensive patterns

Strategy: try-catch

Try / catch

if err := manager.CloseProxy(content); err != nil {
    // teardown best-effort: log, don't fail the close path
    log.Warnf("close proxy plugin errors (non-fatal): %v", err)
}

Prevention

When it happens

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

Common situations: Plugin service restarted or down when proxies close; plugin only partially implements operations and errors on CloseProxy; network blip between frps and the plugin.

Related errors


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