k3s-io/k3s · error
value required for kubelet-arg --%s
Error message
value required for kubelet-arg --%s
What it means
When starting the agent, k3s parses each --kubelet-arg value as either key=val or key followed by the value in the next list element. The keys `config` and `config-dir` are special-cased (k3s copies the referenced kubelet config into its managed dir), and they must carry a non-empty value. A bare or empty-valued `config`/`config-dir` entry aborts agent startup.
Source
Thrown at pkg/daemons/agent/agent.go:128
continue
}
var val string
key := strings.TrimPrefix(extraArgs[i], "--")
if k, v, ok := strings.Cut(key, "="); ok {
// key=val pair
key = k
val = v
} else if len(extraArgs) > i+1 {
// key in this arg, value in next arg
val = extraArgs[i+1]
skipVal = true
}
switch key {
case "config", "config-dir":
if val == "" {
return nil, fmt.Errorf("value required for kubelet-arg --%s", key)
}
strippedArgs[key] = val
default:
args = append(args, extraArgs[i])
}
}
// copy the config file into our managed config dir, unless its already in there
if strippedArgs["config"] != "" && !strings.HasPrefix(strippedArgs["config"], path) {
src := strippedArgs["config"]
dest := filepath.Join(path, "10-cli-config.conf")
if err := agentutil.CopyFile(src, dest, false); err != nil {
return nil, errors.WithMessagef(err, "copy config %q into managed drop-in dir %q", src, dest)
}
}
// copy the config-dir into our managed config dir, unless its already in there
if strippedArgs["config-dir"] != "" && !strings.HasPrefix(strippedArgs["config-dir"], path) {
src := strippedArgs["config-dir"]View on GitHub (pinned to 6ba341e396)
Solutions
- Provide the value: `--kubelet-arg config=/etc/kubernetes/kubelet-config.yaml` (or the key item followed by its value item).
- Remove the bare `config`/`config-dir` entry entirely if no override is wanted - k3s generates its own kubelet config.
- Check the YAML config quoting: write kubelet-arg entries as complete strings like "config=/path", not split items.
Example fix
# before k3s agent --server https://server:6443 --kubelet-arg config # (or in /etc/rancher/k3s/config.yaml: kubelet-arg: ["config"]) # after k3s agent --server https://server:6443 --kubelet-arg config=/etc/kubernetes/kubelet-config.yaml
Defensive patterns
Strategy: validation
Validate before calling
// Validate kubelet-arg entries before launching the agent:
func validateKubeletArgs(args []string) error {
for i := 0; i < len(args); i++ {
key, val, _ := strings.Cut(args[i], "=")
if val == "" && len(args) > i+1 { val = args[i+1] }
if (key == "config" || key == "config-dir") && strings.TrimSpace(val) == "" {
return fmt.Errorf("kubelet-arg %q needs a value", key)
}
}
return nil
} Prevention
- Always write kubelet-arg overrides as single 'key=value' strings.
- Prefer kubelet configuration via the KubeletConfiguration manifest in the server's manifest dir where possible.
- Test generated config files with a dry-run lint before rolling nodes.
When it happens
Trigger: `--kubelet-arg config` as the last item in the list (no next element to use as value), `--kubelet-arg config=`, or a YAML config with `kubelet-arg: ["config"]` / `kubelet-arg: ["config="]` (pkg/daemons/agent/agent.go:120-130).
Common situations: Operator intends to point kubelet at a custom config file but forgets the value; YAML list item written with wrong quoting so the `=` part is lost; trailing empty element from a template.
Related errors
- --token is required
- --server is required
- critical configuration value mismatch between servers
- delegated cgroup v2 controllers are required for rootless
- pids cgroup controller not found
AI-assisted analysis of k3s-io/k3s@6ba341e396 (2026-08-15).
Data as JSON: /api/errors/860f7bf029d92202.
Report an issue: GitHub.