fatedier/frp · error
invalid destination IP address [%s]
Error message
invalid destination IP address [%s]
What it means
The virtual_net visitor plugin could not parse its DestinationIP option: net.ParseIP returned nil for the configured string. DestinationIP must be a literal IPv4 or IPv6 address (host route, /32 or /128), not a CIDR, hostname, or empty string (empty is caught earlier by a dedicated error).
Source
Thrown at pkg/plugin/visitor/virtual_net.go:68
func NewVirtualNetPlugin(pluginCtx PluginContext, options v1.VisitorPluginOptions) (Plugin, error) {
opts := options.(*v1.VirtualNetVisitorPluginOptions)
p := &VirtualNetPlugin{
pluginCtx: pluginCtx,
routes: make([]net.IPNet, 0),
}
p.ctx, p.cancel = context.WithCancel(pluginCtx.Ctx)
if opts.DestinationIP == "" {
return nil, errors.New("destinationIP is required")
}
// Parse DestinationIP and create a host route.
ip := net.ParseIP(opts.DestinationIP)
if ip == nil {
return nil, fmt.Errorf("invalid destination IP address [%s]", opts.DestinationIP)
}
var mask net.IPMask
if ip.To4() != nil {
mask = net.CIDRMask(32, 32) // /32 for IPv4
} else {
mask = net.CIDRMask(128, 128) // /128 for IPv6
}
p.routes = append(p.routes, net.IPNet{IP: ip, Mask: mask})
return p, nil
}
func (p *VirtualNetPlugin) Name() string {
return v1.VisitorPluginVirtualNet
}
func (p *VirtualNetPlugin) Start() {View on GitHub (pinned to 6c8a8d0a97)
Solutions
- Set destinationIP to a single literal IP address, e.g. 10.0.0.1 or fd00::1
- Remove any CIDR suffix, hostname, quotes, or surrounding whitespace
- One plugin instance per destination host; add more visitor entries for additional IPs
Example fix
// before (frpc.toml) [[visitors]] name = "vn" type = "stty" [visitors.plugin] type = "virtual_net" destinationIP = "10.0.0.0/24" // after destinationIP = "10.0.0.3"
Defensive patterns
Strategy: validation
Validate before calling
if net.ParseIP(cfg.DestinationIP) == nil {
return fmt.Errorf("destinationIP must be a literal IP, got %q", cfg.DestinationIP)
} Type guard
func isValidLiteralIP(s string) bool {
return net.ParseIP(strings.TrimSpace(s)) != nil && !strings.Contains(s, "/")
} Prevention
- Remember destinationIP takes one host IP, not a CIDR — use multiple visitors for multiple hosts
- Validate IP strings in config linting before deployment
When it happens
Trigger: Creating a virtual_net visitor plugin with opts.DestinationIP that net.ParseIP rejects — e.g. "10.0.0.0/24", "myhost", "10.0.0" (malformed octets), or trailing whitespace.
Common situations: User expects CIDR support and puts a network prefix in destinationIP; hostname given instead of an IP; copy-paste artifact like quotes or spaces in the TOML value.
Related errors
- plugin [%s] is not registered
- unmarshal visitor plugin error: %v
- unknown visitor plugin type: %s
- unmarshal VisitorPluginOptions error: %v
- xtcp server for [%s] doesn't exist
AI-assisted analysis of fatedier/frp@6c8a8d0a97 (2026-08-15).
Data as JSON: /api/errors/181b8d8b7261d4d9.
Report an issue: GitHub.