fatedier/frp · error

localAddr is required

Error message

localAddr is required

What it means

Validation error from validateHTTP2HTTPSPluginOptions: an frpc proxy uses the http2https plugin but its LocalAddr is empty. The http2https plugin forwards HTTP traffic from the frps side to a local HTTPS service, so it must know the local address (host:port) to dial. This check runs during ValidateProxyConfigurerForClient at client config load.

Source

Thrown at pkg/config/v1/validation/plugin.go:43

	case *v1.HTTP2HTTPSPluginOptions:
		return validateHTTP2HTTPSPluginOptions(v)
	case *v1.HTTPS2HTTPPluginOptions:
		return validateHTTPS2HTTPPluginOptions(v)
	case *v1.HTTPS2HTTPSPluginOptions:
		return validateHTTPS2HTTPSPluginOptions(v)
	case *v1.StaticFilePluginOptions:
		return validateStaticFilePluginOptions(v)
	case *v1.UnixDomainSocketPluginOptions:
		return validateUnixDomainSocketPluginOptions(v)
	case *v1.TLS2RawPluginOptions:
		return validateTLS2RawPluginOptions(v)
	}
	return nil
}

func validateHTTP2HTTPSPluginOptions(c *v1.HTTP2HTTPSPluginOptions) error {
	if c.LocalAddr == "" {
		return errors.New("localAddr is required")
	}
	return nil
}

func validateHTTPS2HTTPPluginOptions(c *v1.HTTPS2HTTPPluginOptions) error {
	if c.LocalAddr == "" {
		return errors.New("localAddr is required")
	}
	return nil
}

func validateHTTPS2HTTPSPluginOptions(c *v1.HTTPS2HTTPSPluginOptions) error {
	if c.LocalAddr == "" {
		return errors.New("localAddr is required")
	}
	return nil
}

View on GitHub (pinned to 6c8a8d0a97)

Solutions

  1. Add localAddr = "127.0.0.1:8443" (host:port of the local HTTPS service) to the plugin options.
  2. Verify the options sit under the plugin's options table (e.g. [proxies.plugin]) so they actually decode into HTTP2HTTPSPluginOptions.
  3. Confirm the local service actually speaks TLS on that address if you chose http2https.

Example fix

# before
[[proxies]]
name = "web"
type = "tcp"
[proxies.plugin]
type = "http2https"

# after
[[proxies]]
name = "web"
type = "tcp"
[proxies.plugin]
type = "http2https"
localAddr = "127.0.0.1:8443"
Defensive patterns

Strategy: validation

Validate before calling

// before validating proxies
if p, ok := cfg.(*v1.HTTP2HTTPSPluginOptions); ok {
    _ = p
}
// simpler: check the decoded typed options
if typed.Type == "http2https" && typed.HTTP2HTTPS.LocalAddr == "" {
    return errors.New("http2https plugin requires localAddr")
}

Type guard

func http2httpsComplete(o *v1.HTTP2HTTPSPluginOptions) bool {
    return o != nil && o.LocalAddr != ""
}

Try / catch

if err := validation.ValidateProxyConfigurerForClient(cfg); err != nil {
    if strings.Contains(err.Error(), "localAddr is required") {
        // add localAddr = "host:port" to the http2https plugin options
    }
    return err
}

Prevention

When it happens

Trigger: A [[proxies]] entry with plugin = "http2https" that has no localAddr in its plugin options (e.g. only plugin type set, or options under the wrong TOML table so LocalAddr decodes to "").

Common situations: Copy-pasting an http_proxy plugin block and switching the type to http2https without adding localAddr; nesting plugin options at the proxy level instead of under [proxies.plugin]; forgetting that https (not plain http) local services need this plugin with an explicit target address.

Related errors


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