{"record":{"id":"c563425800f61a26","repo":"weaviate/weaviate","slug":"rename-s-to-s","errorCode":null,"errorMessage":"rename %s to %s","messagePattern":"rename (.+?) to (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"adapters/repos/db/vector/hnsw/compact/safe_file_writer.go","lineNumber":126,"sourceCode":"\t// 1. Flush buffered writer\n\tif err := s.buffered.Flush(); err != nil {\n\t\treturn errors.Wrap(err, \"flush buffer\")\n\t}\n\n\t// 2. Sync file to disk\n\tif err := s.file.Sync(); err != nil {\n\t\treturn errors.Wrap(err, \"sync file\")\n\t}\n\n\t// 3. Close file (required before rename on some systems)\n\tif err := s.file.Close(); err != nil {\n\t\treturn errors.Wrap(err, \"close file\")\n\t}\n\ts.closed = true\n\n\t// 4. Atomic rename\n\tif err := s.fs.Rename(s.tmpPath, s.finalPath); err != nil {\n\t\treturn errors.Wrapf(err, \"rename %s to %s\", s.tmpPath, s.finalPath)\n\t}\n\n\t// 5. Sync parent directory\n\tif err := diskio.Fsync(filepath.Dir(s.finalPath)); err != nil {\n\t\treturn errors.Wrap(err, \"sync directory\")\n\t}\n\n\ts.committed = true\n\treturn nil\n}\n\n// Abort cleans up the temporary file without committing.\n// Safe to call multiple times or after Commit.\nfunc (s *SafeFileWriter) Abort() error {\n\tif s.committed {\n\t\treturn nil\n\t}\n","sourceCodeStart":108,"sourceCodeEnd":144,"githubUrl":"https://github.com/weaviate/weaviate/blob/75aa4b6d11f8818305aafd4440b4e32794f7ca04/adapters/repos/db/vector/hnsw/compact/safe_file_writer.go#L108-L144","documentation":"Commit() performs an atomic rename of the temp file to its final path; this is the point at which the new file becomes visible. If rename fails, the final file keeps its previous state and the temp file remains on disk. This wrapping includes both paths for easy diagnosis.","triggerScenarios":"Commit() where fs.Rename(tmpPath, finalPath) fails: finalPath exists as a directory, cross-device rename (temp and final on different filesystems), permission denied on the directory, or the temp file was removed concurrently (e.g. by CleanupOrphanedTempFiles running in parallel).","commonSituations":"Data dir mounted across devices so tmp and final paths land on different filesystems (unusual, but possible with symlinked dirs); permission changes on the data directory; concurrent cleanup/garbage collection racing a commit.","solutions":["Ensure temp and final paths resolve to the same filesystem (avoid symlinks/mounts splitting the path).","Check directory write/execute permissions for the Weaviate process user.","Don't run CleanupOrphanedTempFiles concurrently with active writes; it runs at load time — serialize operations.","Investigate the underlying wrapped errno for the exact cause."],"exampleFix":"// before\nerr := writer.Commit() // rename /data/x.condensed.tmp to /data/x.condensed: permission denied\n// after\nchown weaviate:weaviate /data\nerr := writer.Commit()","handlingStrategy":"validation","validationCode":"// Ensure temp and final paths resolve to the same filesystem before writing\nfunc sameDevice(a, b string) (bool, error) {\n\tvar sa, sb unix.Stat_t\n\tif err := unix.Stat(filepath.Dir(a), &sa); err != nil { return false, err }\n\tif err := unix.Stat(filepath.Dir(b), &sb); err != nil { return false, err }\n\treturn sa.Dev == sb.Dev, nil\n}\n// tmpPath := finalPath + suffix -> same dir, but verify no symlinks split devices:\nok, err := sameDevice(tmpPath, finalPath)","typeGuard":null,"tryCatchPattern":"// Rename failure leaves final intact and temp present: safe to retry after fixing cause\nif err := writer.Commit(); err != nil {\n\tif strings.Contains(err.Error(), \"rename\") {\n\t\tlog.Warnf(\"commit rename failed, final file preserved: %v\", err)\n\t\treturn err // do not delete finalPath; fix perms/device and rerun\n\t}\n\treturn err\n}","preventionTips":["Never symlink or bind-mount parts of the shard directory path across devices.","Keep directory permissions consistent for the service user.","Don't run temp-file cleanup concurrently with active compaction/snapshot writes.","Check the wrapped errno in the message to distinguish EACCES/EEXIST/EXDEV."],"tags":["filesystem","rename","atomic-write","permissions"],"backgroundTag":"atomic-rename-failed","analyzedSha":"75aa4b6d11f8818305aafd4440b4e32794f7ca04","analyzedAt":"2026-09-04T14:58:20.392Z","contentChangedAt":"2026-09-04T14:58:20.392Z","schemaVersion":2},"datasetVersion":"2026-09-11T21:17:09.523Z"}