k3s-io/k3s · error

invalid flag use; cannot use --disable-etcd with --datastore

Error message

invalid flag use; cannot use --disable-etcd with --datastore-endpoint

What it means

--disable-etcd marks a server that joins an embedded-etcd cluster through a peer via --server, while --datastore-endpoint selects an external datastore. Setting both leaves the node with two contradictory data-plane instructions, so startup fails fast.

Source

Thrown at pkg/cli/server/server.go:266

	serverConfig.ControlConfig.ClusterReset = cfg.ClusterReset
	serverConfig.ControlConfig.ClusterResetRestorePath = cfg.ClusterResetRestorePath
	serverConfig.ControlConfig.SystemDefaultRegistry = cfg.SystemDefaultRegistry

	if serverConfig.ControlConfig.SupervisorPort == 0 {
		serverConfig.ControlConfig.SupervisorPort = serverConfig.ControlConfig.HTTPSPort
	}

	if serverConfig.ControlConfig.DisableETCD && serverConfig.ControlConfig.JoinURL == "" {
		return errors.New("invalid flag use; --server is required with --disable-etcd")
	}

	if serverConfig.ControlConfig.Datastore.Endpoint != "" && serverConfig.ControlConfig.DisableAPIServer {
		return errors.New("invalid flag use; cannot use --disable-apiserver with --datastore-endpoint")
	}

	if serverConfig.ControlConfig.Datastore.Endpoint != "" && serverConfig.ControlConfig.DisableETCD {
		return errors.New("invalid flag use; cannot use --disable-etcd with --datastore-endpoint")
	}

	if serverConfig.ControlConfig.DisableAPIServer {
		// Servers without a local apiserver need to connect to the apiserver via the proxy load-balancer.
		serverConfig.ControlConfig.APIServerPort = cmds.AgentConfig.LBServerPort
		// If the supervisor and externally-facing apiserver are not on the same port, the proxy will
		// have a separate load-balancer for the apiserver that we need to use instead.
		if serverConfig.ControlConfig.SupervisorPort != serverConfig.ControlConfig.HTTPSPort {
			serverConfig.ControlConfig.APIServerPort = cmds.AgentConfig.LBServerPort - 1
		}
	}

	if cmds.AgentConfig.FlannelIface != "" && len(cmds.AgentConfig.NodeIP.Value()) == 0 {
		ip, err := util.GetIPFromInterface(cmds.AgentConfig.FlannelIface)
		if err != nil {
			return err
		}
		cmds.AgentConfig.NodeIP.Set(ip)

View on GitHub (pinned to 6ba341e396)

Solutions

  1. For external datastores, drop --disable-etcd entirely
  2. For embedded-etcd joining, drop --datastore-endpoint and use --server <url> --token <token>
  3. Unset K3S_DATASTORE_ENDPOINT / K3S_DATASTORE_* variables if the cluster is embedded-etcd

Example fix

# before
k3s server --disable-etcd --datastore-endpoint=postgres://u:p@db:5432/k3s

# after
k3s server --datastore-endpoint=postgres://u:p@db:5432/k3s
Defensive patterns

Strategy: validation

Validate before calling

# reject disable-etcd + datastore-endpoint combo
if printf '%s' "$@" | grep -q -- '--disable-etcd' && { printf '%s' "$@ $K3S_DATASTORE_ENDPOINT" | grep -qE '(--datastore-endpoint|K3S_DATASTORE_ENDPOINT=..)'; }; then
  echo 'cannot use --disable-etcd with --datastore-endpoint'; exit 1
fi

Prevention

When it happens

Trigger: `k3s server --disable-etcd --datastore-endpoint=postgres://...`, or K3S_DATASTORE_ENDPOINT exported in the unit file while config.yaml sets `disable-etcd: true`.

Common situations: Flags left over after converting cluster topology; automation templates that set both 'HA' options defensively; env-var datastore config invisible to the operator reading only config.yaml.

Related errors


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