{"record":{"id":"19dd97ed31db8cb4","repo":"k3s-io/k3s","slug":"failed-to-remove-s-file-v","errorCode":null,"errorMessage":"failed to remove %s file: %v","messagePattern":"failed to remove (.+?) file: (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/server/server.go","lineNumber":527,"sourceCode":"\tsplitter := func(c rune) bool {\n\t\treturn c == ','\n\t}\n\tenvList := []string{}\n\tenvList = append(envList, strings.FieldsFunc(os.Getenv(\"NO_PROXY\"), splitter)...)\n\tenvList = append(envList, strings.FieldsFunc(os.Getenv(\"no_proxy\"), splitter)...)\n\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 {","sourceCodeStart":509,"sourceCodeEnd":545,"githubUrl":"https://github.com/k3s-io/k3s/blob/6ba341e396edc16b8dcae978a7c5e3ac7ee5606e/pkg/server/server.go#L509-L545","documentation":"writeConfigSymlink manages the well-known kubeconfig symlink (e.g. /etc/rancher/k3s/k3s.yaml -> the real kubeconfig in the data dir). It first removes any existing path; if removal fails with anything other than not-exist (permission denied, is-a-directory, read-only filesystem), this wrapped error aborts symlink setup during server start.","triggerScenarios":"Server startup (or reconfiguration) where the symlink path exists but os.Remove fails: the path is a directory, the filesystem is read-only, or the process lacks permission on the parent directory because it exists under a different owner/mode.","commonSituations":"/etc/rancher/k3s/k3s.yaml replaced by a real file or directory owned by root while k3s runs unprivileged; hardening that made /etc/rancher read-only; SELinux/AppArmor denials on unlink; leftover artifacts from other tools writing the same path.","solutions":["Inspect the path: ls -la /etc/rancher/k3s/ and check whether k3s.yaml is a file, directory, or dangling symlink and who owns it.","Remove or rename the offending path manually (rm/rmdir), then restart k3s so the symlink is recreated.","Fix ownership/permissions so the k3s process can write the directory (usually run as root; adjust SELinux contexts if enforcing).","Prevent other tooling from placing files at the symlink path."],"exampleFix":"# before\nls -ld /etc/rancher/k3s/k3s.yaml  # a real file owned by another user\n\n# after\nsudo rm /etc/rancher/k3s/k3s.yaml && sudo systemctl restart k3s\nls -l /etc/rancher/k3s/k3s.yaml  # -> symlink to data dir kubeconfig","handlingStrategy":"validation","validationCode":"// Pre-flight before start: symlink path must be a symlink or absent\nif fi, err := os.Lstat(symlinkPath); err == nil {\n    if fi.Mode()&os.ModeSymlink == 0 {\n        log.Fatalf(\"%s exists and is not a symlink - remove it\", symlinkPath)\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep /etc/rancher writable by the k3s process","Never replace k3s.yaml with a regular file or directory","Audit SELinux/AppArmor policy for unlink permission on /etc/rancher"],"tags":["filesystem","kubeconfig","symlink","startup"],"backgroundTag":null,"analyzedSha":"6ba341e396edc16b8dcae978a7c5e3ac7ee5606e","analyzedAt":"2026-08-15T16:27:54.286Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}