{"record":{"id":"c10ada9a60812e6a","repo":"fatedier/frp","slug":"localpath-is-required","errorCode":null,"errorMessage":"localPath is required","messagePattern":"localPath is required","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/config/v1/validation/plugin.go","lineNumber":64,"sourceCode":"}\n\nfunc validateHTTPS2HTTPPluginOptions(c *v1.HTTPS2HTTPPluginOptions) error {\n\tif c.LocalAddr == \"\" {\n\t\treturn errors.New(\"localAddr is required\")\n\t}\n\treturn nil\n}\n\nfunc validateHTTPS2HTTPSPluginOptions(c *v1.HTTPS2HTTPSPluginOptions) error {\n\tif c.LocalAddr == \"\" {\n\t\treturn errors.New(\"localAddr is required\")\n\t}\n\treturn nil\n}\n\nfunc validateStaticFilePluginOptions(c *v1.StaticFilePluginOptions) error {\n\tif c.LocalPath == \"\" {\n\t\treturn errors.New(\"localPath is required\")\n\t}\n\treturn nil\n}\n\nfunc validateUnixDomainSocketPluginOptions(c *v1.UnixDomainSocketPluginOptions) error {\n\tif c.UnixPath == \"\" {\n\t\treturn errors.New(\"unixPath is required\")\n\t}\n\treturn nil\n}\n\nfunc validateTLS2RawPluginOptions(c *v1.TLS2RawPluginOptions) error {\n\tif c.LocalAddr == \"\" {\n\t\treturn errors.New(\"localAddr is required\")\n\t}\n\treturn nil\n}\n","sourceCodeStart":46,"sourceCodeEnd":82,"githubUrl":"https://github.com/fatedier/frp/blob/6c8a8d0a97d03b44e9528d30b30c70cb9d61b405/pkg/config/v1/validation/plugin.go#L46-L82","documentation":"Validation error from validateStaticFilePluginOptions: the static_file plugin is configured but LocalPath is empty. The static_file plugin serves a local directory over HTTP from the client; the directory to serve is mandatory. This check runs during client-side proxy config validation.","triggerScenarios":"A proxy with plugin = \"static_file\" whose plugin options omit localPath — e.g. only stripPrefix or htmlWelcome was set, or the plugin options table was not attached to the proxy so all fields are defaults.","commonSituations":"Quick file-sharing setups where the author sets the plugin type but forgets the served directory; renaming localPath to path or root in the config; the localPath key placed outside the [proxies.plugin] table.","solutions":["Add localPath = \"/srv/files\" (absolute directory path to expose) to the plugin options.","Optionally add stripPrefix = \"static\" and htmlWelcome = true for the desired serving behavior.","Verify the directory exists and the frpc process has read permission on it."],"exampleFix":"# before\n[[proxies]]\nname = \"files\"\ntype = \"tcp\"\nremotePort = 9000\n[proxies.plugin]\ntype = \"static_file\"\n\n# after\n[[proxies]]\nname = \"files\"\ntype = \"tcp\"\nremotePort = 9000\n[proxies.plugin]\ntype = \"static_file\"\nlocalPath = \"/srv/files\"\nstripPrefix = \"files\"\nhtmlWelcome = true","handlingStrategy":"validation","validationCode":"if pluginType == \"static_file\" && pluginOpts.LocalPath == \"\" {\n    return errors.New(\"static_file plugin requires localPath\")\n}","typeGuard":"func staticFileComplete(o *v1.StaticFilePluginOptions) bool {\n    return o != nil && o.LocalPath != \"\"\n}","tryCatchPattern":"if err := validation.ValidateProxyConfigurerForClient(cfg); err != nil {\n    if strings.Contains(err.Error(), \"localPath is required\") {\n        // add localPath = \"/srv/files\" to the plugin options\n    }\n    return err\n}","preventionTips":["Use the exact key localPath (not path/root).","Ensure the directory exists and frpc can read it.","Include localPath in any static_file config template."],"tags":["config","plugin","static-file","validation","frpc"],"backgroundTag":null,"analyzedSha":"6c8a8d0a97d03b44e9528d30b30c70cb9d61b405","analyzedAt":"2026-08-15T06:53:27.215Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}