k3s-io/k3s · error
Flannel configuration not defined
Error message
Flannel configuration not defined
What it means
createFlannelConf refuses to continue when nodeConfig.Flannel.ConfFile is empty. k3s normally populates ConfFile during agent startup with the path where the generated flannel config is written; hitting this error means the flannel sub-system was invoked before that defaulting happened, or the value was explicitly cleared. It protects against silently writing a config to an unspecified location.
Source
Thrown at pkg/agent/flannel/setup.go:176
cniConfJSON := cniConf
if goruntime.GOOS == "windows" {
extIface, err := LookupExtInterface(nodeConfig.Flannel.Iface, ipv4)
if err != nil {
return err
}
cniConfJSON = strings.ReplaceAll(cniConfJSON, "%IPV4_ADDRESS%", extIface.IfaceAddr.String())
cniConfJSON = strings.ReplaceAll(cniConfJSON, "%CLUSTER_CIDR%", nodeConfig.AgentConfig.ClusterCIDR.String())
cniConfJSON = strings.ReplaceAll(cniConfJSON, "%SERVICE_CIDR%", nodeConfig.AgentConfig.ServiceCIDR.String())
}
return agentutil.WriteFile(p, cniConfJSON)
}
func createFlannelConf(nodeConfig *config.Node) error {
logrus.Debugf("Creating the flannel configuration for backend %s in file %s", nodeConfig.Flannel.Backend, nodeConfig.Flannel.ConfFile)
if nodeConfig.Flannel.ConfFile == "" {
return errors.New("Flannel configuration not defined")
}
if nodeConfig.Flannel.ConfOverride {
logrus.Infof("Using custom flannel conf defined at %s", nodeConfig.Flannel.ConfFile)
return nil
}
nm, err := findNetMode(nodeConfig.AgentConfig.ClusterCIDRs)
if err != nil {
logrus.Fatalf("Flannel error checking netMode: %v", err)
return err
}
confJSON := flannelConf
if nm.IPv4Enabled() {
confJSON = strings.ReplaceAll(confJSON, "%IPV4_ENABLED%", "true")
if nm.IPv6Enabled() {
for _, cidr := range nodeConfig.AgentConfig.ClusterCIDRs {
if utilsnet.IsIPv4(cidr.IP) {
confJSON = strings.ReplaceAll(confJSON, "%CIDR%", cidr.String())
breakView on GitHub (pinned to 6ba341e396)
Solutions
- Let the normal agent startup path populate Flannel.ConfFile (do not bypass the defaulting stage)
- If configuring manually, set the conf file path explicitly, e.g. nodeConfig.Flannel.ConfFile = "/run/flannel/flannel-conf.json" or the standard /etc/rancher/k3s/flannel/conf location
- Pass --flannel-conf=/path/to/conf when overriding so ConfFile is never empty
Example fix
// before nodeConfig.Flannel.ConfFile = "" createFlannelConf(nodeConfig) // -> Flannel configuration not defined // after nodeConfig.Flannel.ConfFile = "/etc/rancher/k3s/flannel/conf.json" createFlannelConf(nodeConfig)
Defensive patterns
Strategy: validation
Validate before calling
func hasFlannelConfFile(nodeConfig *config.Node) error {
if nodeConfig.Flannel.ConfFile == "" {
return errors.New("Flannel.ConfFile must be set (agent defaulting skipped?)")
}
return nil
} Prevention
- Library consumers: run the standard agent config defaulting before touching flannel setup
- Never blank Flannel.ConfFile; if overriding, point --flannel-conf at a real file
- Unit-test config.Node construction to assert ConfFile is non-empty
When it happens
Trigger: Calling the flannel setup path (library consumers, tests, or tools) on a config.Node that never went through the agent config defaulting that sets Flannel.ConfFile; explicitly setting the flannel conf path to an empty string.
Common situations: Embedding k3s agent code in another binary that builds config.Node manually; unit/integration harnesses that exercise flannel setup directly; a config template that unsets flannel-conf.
Related errors
- ipv4 mode requested but no ipv4 network provided
- Failed checking netMode
- VPN Error. Tailscale requires a JoinKey
- failed to determine MTU for %s interface
- unsupported flannel backend '%s' for Windows
AI-assisted analysis of k3s-io/k3s@6ba341e396 (2026-08-15).
Data as JSON: /api/errors/ea67935da6641e7e.
Report an issue: GitHub.