{"record":{"id":"83f46e4cbc7e06f4","repo":"hyperledger/fabric","slug":"error-renaming-temp-file-s","errorCode":null,"errorMessage":"error renaming temp file '%s'","messagePattern":"error renaming temp file '(.+?)'","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/chaincode/persistence/persistence.go","lineNumber":69,"sourceCode":"\t}\n\tdefer os.Remove(tmpFile.Name())\n\n\tif n, err := tmpFile.Write(data); err != nil || n != len(data) {\n\t\tif err == nil {\n\t\t\terr = errors.Errorf(\n\t\t\t\t\"failed to write the entire content of the file, expected %d, wrote %d\",\n\t\t\t\tlen(data), n,\n\t\t\t)\n\t\t}\n\t\treturn errors.Wrapf(err, \"error writing to temp file '%s'\", tmpFile.Name())\n\t}\n\n\tif err := tmpFile.Close(); err != nil {\n\t\treturn errors.Wrapf(err, \"error closing temp file '%s'\", tmpFile.Name())\n\t}\n\n\tif err := os.Rename(tmpFile.Name(), filepath.Join(path, name)); err != nil {\n\t\treturn errors.Wrapf(err, \"error renaming temp file '%s'\", tmpFile.Name())\n\t}\n\n\treturn nil\n}\n\n// Remove removes a file from the filesystem - used for rolling back an in-flight\n// Save operation upon a failure\nfunc (f *FilesystemIO) Remove(name string) error {\n\treturn os.Remove(name)\n}\n\n// ReadFile reads a file from the filesystem\nfunc (f *FilesystemIO) ReadFile(filename string) ([]byte, error) {\n\treturn os.ReadFile(filename)\n}\n\n// ReadDir reads a directory from the filesystem\nfunc (f *FilesystemIO) ReadDir(dirname string) ([]os.FileInfo, error) {","sourceCodeStart":51,"sourceCodeEnd":87,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/core/chaincode/persistence/persistence.go#L51-L87","documentation":"WriteFile achieves atomic persistence by os.Rename of the temp file (.ccpackage.*) to its final name inside the same directory. If the rename fails, the install does not complete and the error is wrapped with the temp file's name.","triggerScenarios":"os.Rename(tmpFile.Name(), filepath.Join(path, name)) fails: target name invalid, cross-device rename (path/name resolution changed), target directory removed mid-operation, or permission problems on the directory.","commonSituations":"External cleanup job deleting the chaincodes directory while an install is in flight; the destination filename (derived from PackageID) colliding with a directory; exotic mounts where rename semantics differ.","solutions":["Verify the target directory still exists and is writable at the time of the rename","Ensure no external process/jobs remove or lock files inside the chaincode install directory","Check the wrapped OS error for the precise cause (ENOENT, EXDEV, EACCES, EISDIR) and fix accordingly","Retry the install once the directory is in a consistent state"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"func ensureRenamable(dir, final string) error {\n    if info, err := os.Stat(filepath.Join(dir, final)); err == nil && info.IsDir() {\n        return errors.New(\"destination name exists as a directory\")\n    }\n    if err := unix.Access(dir, unix.W_OK); err != nil { return errors.New(\"dir not writable\") }\n    return nil\n}","typeGuard":null,"tryCatchPattern":"if err := io.WriteFile(path, name, data); err != nil {\n    if strings.Contains(err.Error(), \"error renaming temp file\") {\n        log.Errorf(\"install dir state changed during write: %v\", err)\n        // re-verify directory exists, then retry once\n    }\n    return err\n}","preventionTips":["Exclude the chaincode install directory from external cleanup jobs (tmpwatch, cron sweeps)","Do not nest files/directories under names the store may use","Keep the data directory on a single filesystem so rename stays same-device"],"tags":["filesystem","atomic-write","rename"],"backgroundTag":"file-rename-failed","analyzedSha":"2736b63f8fd5932511d56fe68b7039d15977f7f6","analyzedAt":"2026-09-04T08:52:36.465Z","contentChangedAt":"2026-09-04T08:52:36.465Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}