{"record":{"id":"ff6860258d406d31","repo":"fatedier/frp","slug":"plugin-s-is-not-registered","errorCode":null,"errorMessage":"plugin [%s] is not registered","messagePattern":"plugin \\[(.+?)\\] is not registered","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/plugin/client/plugin.go","lineNumber":52,"sourceCode":"}\n\n// Creators is used for create plugins to handle connections.\nvar creators = make(map[string]CreatorFn)\n\ntype CreatorFn func(pluginCtx PluginContext, options v1.ClientPluginOptions) (Plugin, error)\n\nfunc Register(name string, fn CreatorFn) {\n\tif _, exist := creators[name]; exist {\n\t\tpanic(fmt.Sprintf(\"plugin [%s] is already registered\", name))\n\t}\n\tcreators[name] = fn\n}\n\nfunc Create(pluginName string, pluginCtx PluginContext, options v1.ClientPluginOptions) (p Plugin, err error) {\n\tif fn, ok := creators[pluginName]; ok {\n\t\tp, err = fn(pluginCtx, options)\n\t} else {\n\t\terr = fmt.Errorf(\"plugin [%s] is not registered\", pluginName)\n\t}\n\treturn\n}\n\ntype ConnectionInfo struct {\n\tConn           io.ReadWriteCloser\n\tUnderlyingConn net.Conn\n\n\tProxyProtocolHeader *pp.Header\n\tSrcAddr             net.Addr\n\tDstAddr             net.Addr\n}\n\ntype Plugin interface {\n\tName() string\n\n\tHandle(ctx context.Context, connInfo *ConnectionInfo)\n\tClose() error","sourceCodeStart":34,"sourceCodeEnd":70,"githubUrl":"https://github.com/fatedier/frp/blob/6c8a8d0a97d03b44e9528d30b30c70cb9d61b405/pkg/plugin/client/plugin.go#L34-L70","documentation":"Client-side plugin factory lookup failed: Create() was asked for a plugin name that has no registered CreatorFn in the client plugin registry. The registry is populated by init() functions of built-in plugins (http, https2http, socks5, static_file, unix_domain_socket, ...), so an unknown name means either a typo or a plugin type only available in a different build.","triggerScenarios":"A proxy config whose [proxies.plugin].type is not one of the registered client plugin names — misspelled type string, or a server-side-only plugin name used on the client.","commonSituations":"type = \"https2htp\" typo; using a plugin introduced in a newer frp version while running an older frpc; custom plugin compiled out of the build; confusing server plugins (op-style) with client proxy plugins.","solutions":["Check the plugin type string against the supported list in the frp docs for your version","Upgrade frpc to the version that ships the plugin you want","If it is a custom plugin, register it with plugin/client.Register before Create is called"],"exampleFix":"// before\n[proxies.plugin]\ntype = \"https2htp\"  // typo\nlocalAddr = \"127.0.0.1:80\"\n\n// after\ntype = \"https2http\"\nlocalAddr = \"127.0.0.1:80\"","handlingStrategy":"validation","validationCode":"// Reject config before starting the proxy\nif !plugin.ValidTypes()[cfg.Plugin.Type] {\n    return fmt.Errorf(\"unknown client plugin type %q; valid: %v\", cfg.Plugin.Type, plugin.ValidTypes())\n}","typeGuard":null,"tryCatchPattern":"if _, err := plugin.Create(name, pCtx, opts); err != nil {\n    if strings.Contains(err.Error(), \"is not registered\") {\n        return fmt.Errorf(\"config error: %w — check plugin type spelling and frpc version\", err)\n    }\n    return err\n}","preventionTips":["Validate plugin type strings against docs for the deployed frpc version","Add config-schema validation in CI to catch typos early","Upgrade frpc before adopting newly added plugin types"],"tags":["plugin","configuration","registry","go"],"backgroundTag":null,"analyzedSha":"6c8a8d0a97d03b44e9528d30b30c70cb9d61b405","analyzedAt":"2026-08-15T06:53:27.215Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}