{"record":{"id":"4e691e72561b0d5a","repo":"k3s-io/k3s","slug":"failed-to-create-symlink-v","errorCode":null,"errorMessage":"failed to create symlink: %v","messagePattern":"failed to create symlink: (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/server/server.go","lineNumber":533,"sourceCode":"\tenvList = append(envList,\n\t\t\".svc\",\n\t\t\".\"+config.ClusterDomain,\n\t\tutil.JoinIPNets(config.ClusterIPRanges),\n\t\tutil.JoinIPNets(config.ServiceIPRanges),\n\t)\n\tos.Unsetenv(\"no_proxy\")\n\treturn os.Setenv(\"NO_PROXY\", strings.Join(envList, \",\"))\n}\n\nfunc writeConfigSymlink(kubeconfig, kubeconfigSymlink string) error {\n\tif err := os.Remove(kubeconfigSymlink); err != nil && !os.IsNotExist(err) {\n\t\treturn fmt.Errorf(\"failed to remove %s file: %v\", kubeconfigSymlink, err)\n\t}\n\tif err := os.MkdirAll(filepath.Dir(kubeconfigSymlink), 0755); err != nil {\n\t\treturn fmt.Errorf(\"failed to create path for symlink: %v\", err)\n\t}\n\tif err := os.Symlink(kubeconfig, kubeconfigSymlink); err != nil {\n\t\treturn fmt.Errorf(\"failed to create symlink: %v\", err)\n\t}\n\treturn nil\n}\n\nfunc isSymlink(config string) bool {\n\tif fi, err := os.Lstat(config); err == nil && (fi.Mode()&os.ModeSymlink == os.ModeSymlink) {\n\t\treturn true\n\t}\n\treturn false\n}\n\nfunc setNodeLabelsAndAnnotations(ctx context.Context, nodes v1.NodeClient, config *Config) error {\n\tif config.DisableAgent || config.ControlConfig.DisableAPIServer {\n\t\treturn nil\n\t}\n\n\tpatcher := util.NewPatcher[*corev1.Node](nodes)\n\treturn wait.PollUntilContextCancel(ctx, time.Second, true, func(ctx context.Context) (bool, error) {","sourceCodeStart":515,"sourceCodeEnd":551,"githubUrl":"https://github.com/k3s-io/k3s/blob/6ba341e396edc16b8dcae978a7c5e3ac7ee5606e/pkg/server/server.go#L515-L551","documentation":"The final step of writeConfigSymlink calls os.Symlink to point the well-known kubeconfig path at the data-dir kubeconfig. Any failure creating the symlink - most commonly the target path already exists again (race with another process), permission on the parent directory, or symlink privilege restrictions - is returned as this error.","triggerScenarios":"Server start where os.Symlink(kubeconfig, kubeconfigSymlink) fails: another k3s instance/loop recreated the path between the Remove and Symlink calls, the parent dir is not writable, or on Windows without the SeCreateSymbolicLinkPrivilege (developer mode / admin requirement).","commonSituations":"Two k3s servers sharing or racing over the same /etc/rancher path; system hardening that revoked write permission right after startup began; running k3s on Windows hosts without developer mode; antivirus/EDR briefly locking the new symlink.","solutions":["Check for and clear the target path: ls -la /etc/rancher/k3s/ and remove a stale k3s.yaml, then restart k3s.","Ensure only one k3s instance manages a given /etc/rancher directory (check for duplicate systemd units or containers).","On Windows, run from an elevated shell or enable Developer Mode so unprivileged symlink creation is allowed.","Confirm write permission on the parent directory and absence of MAC-policy denials in the wrapped error."],"exampleFix":"# before: stale target left by a racing instance\nls -l /etc/rancher/k3s/k3s.yaml  # regular file, k3s fails at os.Symlink\n\n# after\nsudo rm /etc/rancher/k3s/k3s.yaml && sudo systemctl restart k3s","handlingStrategy":"retry","validationCode":"// Check target is absent or already the right symlink before start\nif fi, err := os.Lstat(target); err == nil {\n    if fi.Mode()&os.ModeSymlink != 0 { /* already linked, ok */ } else {\n        os.Remove(target) // clear regular file left by another tool\n    }\n}","typeGuard":null,"tryCatchPattern":"// Handle EEXIST-style races by clearing and retrying once\nif err := writeConfigSymlink(kc, sym); err != nil {\n    if strings.Contains(err.Error(), \"failed to create symlink\") {\n        os.Remove(sym)\n        err = writeConfigSymlink(kc, sym) // single deterministic retry\n    }\n    if err != nil { return err }\n}","preventionTips":["Ensure exactly one k3s instance manages a given /etc/rancher path","On Windows, enable Developer Mode or run elevated","Keep the parent directory writable throughout startup"],"tags":["filesystem","symlink","kubeconfig","startup"],"backgroundTag":null,"analyzedSha":"6ba341e396edc16b8dcae978a7c5e3ac7ee5606e","analyzedAt":"2026-08-15T16:27:54.286Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}