k3s-io/k3s · error
tailscale does not provide an ipv4 address
Error message
tailscale does not provide an ipv4 address
What it means
The mirror of the IPv6 case: when the node runs dual-stack or IPv4-only and the tailscale/VPN integration is active, k3s overwrites the advertise address with the VPN's IPv4 address. If the VPN reports no IPv4 address, startup fails instead of advertising an unreachable address.
Solutions
- Make the tailnet provide the node an IPv4 address (or fix the tailscale config) and retry
- Move the node to IPv6-only node-ip so the IPv6 branch applies
- Drop --vpn-config/--vpn-auth and configure --advertise-address manually
Example fix
# before k3s server --node-ip=10.0.0.10 --vpn-config=hostname=tsw1 # tailnet is v6-only # after k3s server --node-ip=fd00::10 --vpn-config=hostname=tsw1
Defensive patterns
Strategy: validation
Validate before calling
// before enabling vpn integration on ipv4/dual-stack nodes
info, _ := vpn.GetInfoFromExecutor()
if info != nil && info.IPv4Address == nil && !utilsnet.IsIPv6(net.ParseIP(cmds.AgentConfig.NodeIP.Value()[0])) {
return errors.New("VPN has no IPv4 address; fix tailscale or drop --vpn-* flags")
} Type guard
func vpnHasIPv4(vpnInfo *vpn.Info) bool { return vpnInfo != nil && vpnInfo.IPv4Address != nil } Prevention
- Verify with `tailscale ip -4` that the node has a v4 address before using VPN advertise-address
- Keep node IP family consistent with tailnet addressing
- Treat vpn-info hooks as external input: validate both address fields
When it happens
Trigger: Node with IPv4/dual-stack node-ip started with --vpn-config/--vpn-auth where vpnInfo.IPv4Address is nil — e.g. an IPv6-only tailnet or tailscale returning only v6 addresses.
Common situations: IPv6-only tailnets where tailscale has no A record for the node; VPN executor returning incomplete info; mixing IPv6-only tailscale deployment with IPv4 k3s nodes.
Related errors
- incorrect netMode for flannel tailscale backend
- tailscale does not provide an ipv6 address
- failed to run tailscale debug prefs
- failed to run tailscale status --json
- failed to unmarshal tailscale output
AI-assisted analysis of k3s-io/k3s@6ba341e396 (2026-08-15).
Data as JSON: /api/errors/96cdbcabf4bb7d4e.
Report an issue: GitHub.
Appendix: source
Thrown at pkg/cli/server/server.go:539
if vpnInfo.IPv6Address != nil {
logrus.Infof("Changed advertise-address to %v due to VPN", vpnInfo.IPv6Address)
if serverConfig.ControlConfig.AdvertiseIP != "" {
logrus.Warn("Conflict in the config detected. VPN integration overwrites advertise-address but the config is setting the advertise-address parameter")
}
serverConfig.ControlConfig.AdvertiseIP = vpnInfo.IPv6Address.String()
} else {
return errors.New("tailscale does not provide an ipv6 address")
}
} else {
// We are in dual-stack or ipv4-only mode
if vpnInfo.IPv4Address != nil {
logrus.Infof("Changed advertise-address to %v due to VPN", vpnInfo.IPv4Address)
if serverConfig.ControlConfig.AdvertiseIP != "" {
logrus.Warn("Conflict in the config detected. VPN integration overwrites advertise-address but the config is setting the advertise-address parameter")
}
serverConfig.ControlConfig.AdvertiseIP = vpnInfo.IPv4Address.String()
} else {
return errors.New("tailscale does not provide an ipv4 address")
}
}
logrus.Warn("Etcd IP (PrivateIP) remains the local IP. Running etcd traffic over VPN is not recommended due to performance issues")
} else {
// if not set, try setting advertise-ip from agent node-external-ip
if serverConfig.ControlConfig.AdvertiseIP == "" && len(cmds.AgentConfig.NodeExternalIP.Value()) != 0 {
serverConfig.ControlConfig.AdvertiseIP = util.GetFirstValidIPString(cmds.AgentConfig.NodeExternalIP.Value())
}
// if not set, try setting advertise-ip from agent node-ip
if serverConfig.ControlConfig.AdvertiseIP == "" && len(cmds.AgentConfig.NodeIP.Value()) != 0 {
serverConfig.ControlConfig.AdvertiseIP = util.GetFirstValidIPString(cmds.AgentConfig.NodeIP.Value())
}
}
// if we ended up with any advertise-ips, ensure they're added to the SAN list
// before PrepareServer generates the apiserver serving certificate;
// note that kube-apiserver does not support dual-stack advertise-ip as of 1.21.0:View on GitHub (pinned to 6ba341e396)