{"record":{"id":"517e870d33a82075","repo":"kubernetes/kops","slug":"error-during-file-write-of-q-rename-failed-v","errorCode":null,"errorMessage":"error during file write of %q: rename failed: %v","messagePattern":"error during file write of %q: rename failed: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"util/pkg/vfs/fs.go","lineNumber":78,"sourceCode":"\n\tf, err := os.CreateTemp(dir, \"tmp\")\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error creating temp file in %q: %v\", dir, err)\n\t}\n\n\t// Note from here on in we have to close f and delete or rename the temp file\n\ttempfile := f.Name()\n\n\t_, err = io.Copy(f, data)\n\n\tif closeErr := f.Close(); err == nil {\n\t\terr = closeErr\n\t}\n\n\tif err == nil {\n\t\terr = os.Rename(tempfile, p.location)\n\t\tif err != nil {\n\t\t\terr = fmt.Errorf(\"error during file write of %q: rename failed: %v\", p.location, err)\n\t\t}\n\t}\n\n\tif err == nil {\n\t\treturn nil\n\t}\n\n\t// Something went wrong; try to remove the temp file\n\tif removeErr := os.Remove(tempfile); removeErr != nil {\n\t\tklog.Warningf(\"unable to remove temp file %q: %v\", tempfile, removeErr)\n\t}\n\n\treturn err\n}\n\n// To prevent concurrent creates on the same file while maintaining atomicity of writes,\n// we take a process-wide lock during the operation.\n// Not a great approach, but fine for a single process (with low concurrency)","sourceCodeStart":60,"sourceCodeEnd":96,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/util/pkg/vfs/fs.go#L60-L96","documentation":"WriteFile stages data in a temp file and then atomically moves it into place with os.Rename(tempfile, p.location). This error is thrown when the rename fails — typically the temp file and target are on different filesystems/mounts, or the target directory's permissions changed. At this point the data was written and closed, but the final file was not updated.","triggerScenarios":"Calling CreateFile/WriteFile where os.Rename fails: target directory not writable (cannot replace/create the final name), p.location is a directory, or the temp dir and target are on different mount points after a bind mount/overlay change.","commonSituations":"p.location pointing at an existing directory instead of a file, the parent directory becoming read-only mid-write, container volume mounts making the temp file land on a different device than the target.","solutions":["Ensure p.location is a file path, not an existing directory, and its parent is writable.","Verify the temp file and target reside on the same filesystem (no mount point inserted between them).","Check directory permissions/immutable flags (lsattr) and remove the immutable bit if set.","Re-run the write; rename is atomic and a transient mount change is the usual culprit."],"exampleFix":"// before\nFSPath{location: \"/srv/state/cluster\"} // cluster exists as a directory -> rename fails\n// after\nFSPath{location: \"/srv/state/cluster/spec.yaml\"}","handlingStrategy":"try-catch","validationCode":"if fi, err := os.Stat(target); err == nil && fi.IsDir() {\n    return fmt.Errorf(\"target %s is a directory; rename would fail\", target)\n}\n// same-filesystem check for the staging directory\nif err := sameFilesystem(filepath.Dir(target), filepath.Dir(target)); err != nil {\n    return err\n}","typeGuard":null,"tryCatchPattern":"if err := p.WriteFile(ctx, data, acl); err != nil && strings.Contains(err.Error(), \"rename failed\") {\n    if errors.Is(errors.Unwrap(errors.Unwrap(err)), syscall.EXDEV) {\n        return fmt.Errorf(\"temp file and target are on different filesystems: %w\", err)\n    }\n    return err\n}","preventionTips":["Point FSPath at a file path, never an existing directory.","Keep temp files and targets on the same mount (avoid bind-mount surprises).","Keep parent directories writable and free of immutable flags (chattr +i)."],"tags":["filesystem","vfs","rename"],"backgroundTag":"rename-failed","analyzedSha":"4c8573c808a73d578c5eadc86d410646ea0b0d73","analyzedAt":"2026-09-05T04:13:19.212Z","contentChangedAt":"2026-09-05T04:13:19.212Z","schemaVersion":2},"datasetVersion":"2026-09-12T07:17:12.445Z"}