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())
					break

View on GitHub (pinned to 6ba341e396)

Solutions

  1. Let the normal agent startup path populate Flannel.ConfFile (do not bypass the defaulting stage)
  2. 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
  3. 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

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


AI-assisted analysis of k3s-io/k3s@6ba341e396 (2026-08-15). Data as JSON: /api/errors/ea67935da6641e7e. Report an issue: GitHub.